@@ -1180,4 +1180,72 @@ describe('Pages Router', () => {
11801180 } ) ;
11811181 } ) ;
11821182 } ) ;
1183+
1184+ describe ( 'XSS Protection' , ( ) => {
1185+ beforeEach ( async ( ) => {
1186+ await reconfigureServer ( {
1187+ appId : 'test' ,
1188+ appName : 'exampleAppname' ,
1189+ publicServerURL : 'http://localhost:8378/1' ,
1190+ pages : { enableRouter : true } ,
1191+ } ) ;
1192+ } ) ;
1193+
1194+ it ( 'should escape XSS payloads in token parameter' , async ( ) => {
1195+ const xssPayload = '"><script>alert("XSS")</script>' ;
1196+ const response = await request ( {
1197+ url : `http://localhost:8378/1/apps/choose_password?token=${ encodeURIComponent ( xssPayload ) } &username=test&appId=test` ,
1198+ } ) ;
1199+
1200+ expect ( response . status ) . toBe ( 200 ) ;
1201+ expect ( response . text ) . not . toContain ( '<script>alert("XSS")</script>' ) ;
1202+ expect ( response . text ) . toContain ( '"><script>' ) ;
1203+ } ) ;
1204+
1205+ it ( 'should escape XSS in username parameter' , async ( ) => {
1206+ const xssUsername = '<img src=x onerror=alert(1)>' ;
1207+ const response = await request ( {
1208+ url : `http://localhost:8378/1/apps/choose_password?username=${ encodeURIComponent ( xssUsername ) } &appId=test` ,
1209+ } ) ;
1210+
1211+ expect ( response . status ) . toBe ( 200 ) ;
1212+ expect ( response . text ) . not . toContain ( '<img src=x onerror=alert(1)>' ) ;
1213+ expect ( response . text ) . toContain ( '<img' ) ;
1214+ } ) ;
1215+
1216+ it ( 'should escape XSS in locale parameter' , async ( ) => {
1217+ const xssLocale = '"><svg/onload=alert(1)>' ;
1218+ const response = await request ( {
1219+ url : `http://localhost:8378/1/apps/choose_password?locale=${ encodeURIComponent ( xssLocale ) } &appId=test` ,
1220+ } ) ;
1221+
1222+ expect ( response . status ) . toBe ( 200 ) ;
1223+ expect ( response . text ) . not . toContain ( '<svg/onload=alert(1)>' ) ;
1224+ expect ( response . text ) . toContain ( '"><svg' ) ;
1225+ } ) ;
1226+
1227+ it ( 'should handle legitimate usernames with quotes correctly' , async ( ) => {
1228+ const username = "O'Brien" ;
1229+ const response = await request ( {
1230+ url : `http://localhost:8378/1/apps/choose_password?username=${ encodeURIComponent ( username ) } &appId=test` ,
1231+ } ) ;
1232+
1233+ expect ( response . status ) . toBe ( 200 ) ;
1234+ // Should be properly escaped as HTML entity
1235+ expect ( response . text ) . toContain ( 'O'Brien' ) ;
1236+ // Should NOT contain unescaped quote that breaks HTML
1237+ expect ( response . text ) . not . toContain ( 'value="O\'Brien"' ) ;
1238+ } ) ;
1239+
1240+ it ( 'should handle legitimate usernames with ampersands correctly' , async ( ) => {
1241+ const username = 'Smith & Co' ;
1242+ const response = await request ( {
1243+ url : `http://localhost:8378/1/apps/choose_password?username=${ encodeURIComponent ( username ) } &appId=test` ,
1244+ } ) ;
1245+
1246+ expect ( response . status ) . toBe ( 200 ) ;
1247+ // Should be properly escaped
1248+ expect ( response . text ) . toContain ( 'Smith & Co' ) ;
1249+ } ) ;
1250+ } ) ;
11831251} ) ;
0 commit comments