@@ -39,12 +39,39 @@ export default async function signin(params: {
3939 const normalizer : ( identifier : string ) => string =
4040 provider . normalizeIdentifier ??
4141 ( ( identifier ) => {
42+ const trimmedEmail = identifier . trim ( )
43+
44+ // Validate email format according to RFC 5321/5322
45+ // Reject emails with quotes in the local part to prevent address parser exploits
46+ // Reject multiple @ symbols which could indicate an exploit attempt
47+ const atCount = ( trimmedEmail . match ( / @ / g) ?? [ ] ) . length
48+ if ( atCount !== 1 ) {
49+ throw new Error ( "Invalid email address format." )
50+ }
51+
52+ // Check for quotes in the email address which could be used for exploits
53+ if ( trimmedEmail . includes ( '"' ) ) {
54+ throw new Error ( "Invalid email address format." )
55+ }
56+
4257 // Get the first two elements only,
4358 // separated by `@` from user input.
44- let [ local , domain ] = identifier . toLowerCase ( ) . trim ( ) . split ( "@" )
59+ let [ local , domain ] = trimmedEmail . toLowerCase ( ) . split ( "@" )
60+
61+ // Validate that both local and domain parts exist and are non-empty
62+ if ( ! local || ! domain ) {
63+ throw new Error ( "Invalid email address format." )
64+ }
65+
4566 // The part before "@" can contain a ","
4667 // but we remove it on the domain part
4768 domain = domain . split ( "," ) [ 0 ]
69+
70+ // Additional validation: domain must have at least one dot
71+ if ( ! domain . includes ( "." ) ) {
72+ throw new Error ( "Invalid email address format." )
73+ }
74+
4875 return `${ local } @${ domain } `
4976 } )
5077
0 commit comments