@@ -44,7 +44,7 @@ describe('Runtime checks: should allow element modification', () => {
44
44
scriptElement . id = 'scripty'
45
45
scriptElement . setAttribute ( 'type' , 'application/evilscript' )
46
46
document . body . appendChild ( scriptElement )
47
- const hadInspectorNode = ! ! document . querySelector ( 'ddg-runtime-checks' )
47
+ const hadInspectorNode = scriptElement === document . querySelector ( 'ddg-runtime-checks' )
48
48
// Continue to modify the script element after it has been added to the DOM
49
49
scriptElement . integrity = 'sha256-123'
50
50
// @ts -expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
@@ -101,7 +101,7 @@ describe('Runtime checks: should allow element modification', () => {
101
101
scriptElement . id = 'scripty2'
102
102
scriptElement . setAttribute ( 'type' , 'application/javascript' )
103
103
document . body . appendChild ( scriptElement )
104
- const hadInspectorNode = ! ! document . querySelector ( 'ddg-runtime-checks' )
104
+ const hadInspectorNode = scriptElement === document . querySelector ( 'ddg-runtime-checks' )
105
105
// Continue to modify the script element after it has been added to the DOM
106
106
// @ts -expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
107
107
scriptElement . madeUpProp = 'val'
@@ -174,7 +174,7 @@ describe('Runtime checks: should allow element modification', () => {
174
174
document . body . appendChild ( scriptElement )
175
175
await Promise . all ( [ promise , promise2 ] )
176
176
177
- const hadInspectorNode = ! ! document . querySelector ( 'ddg-runtime-checks' )
177
+ const hadInspectorNode = scriptElement === document . querySelector ( 'ddg-runtime-checks' )
178
178
// Continue to modify the script element after it has been added to the DOM
179
179
// @ts -expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
180
180
scriptElement . madeUpProp = 'val'
@@ -224,7 +224,6 @@ describe('Runtime checks: should allow element modification', () => {
224
224
}
225
225
}
226
226
} )
227
- // And now with a script that will execute
228
227
const scriptResult4 = await page . evaluate (
229
228
( ) => {
230
229
function getAttributeValues ( el ) {
@@ -254,7 +253,7 @@ describe('Runtime checks: should allow element modification', () => {
254
253
scriptElement . setAttribute ( 'madeUpAttr1' , '1' )
255
254
scriptElement . setAttribute ( 'madeUpAttr2' , '2' )
256
255
document . body . appendChild ( scriptElement )
257
- const hadInspectorNode = ! ! document . querySelector ( 'ddg-runtime-checks' )
256
+ const hadInspectorNode = scriptElement === document . querySelector ( 'ddg-runtime-checks' )
258
257
// Continue to modify the script element after it has been added to the DOM
259
258
// @ts -expect-error made up prop is unknown to TS
260
259
scriptElement . madeUpProp1 = 'val'
@@ -295,4 +294,142 @@ describe('Runtime checks: should allow element modification', () => {
295
294
nodeAndFakeNodeMatch : false
296
295
} )
297
296
} )
297
+
298
+ it ( 'Script that should filter props and attributes' , async ( ) => {
299
+ const port = server . address ( ) . port
300
+ const page = await browser . newPage ( )
301
+ await gotoAndWait ( page , `http://localhost:${ port } /blank.html` , {
302
+ site : {
303
+ enabledFeatures : [ 'runtimeChecks' ]
304
+ } ,
305
+ featureSettings : {
306
+ runtimeChecks : {
307
+ taintCheck : 'enabled' ,
308
+ matchAllDomains : 'enabled' ,
309
+ matchAllStackDomains : 'enabled' ,
310
+ overloadInstanceOf : 'enabled'
311
+ }
312
+ }
313
+ } )
314
+ const scriptResult5 = await page . evaluate (
315
+ ( ) => {
316
+ // @ts -expect-error Undefined property for testing
317
+ window . scripty5Ran = false
318
+ const myScript = document . createElement ( 'script' )
319
+ myScript . innerText = 'window.scripty5Ran = true'
320
+ Object . setPrototypeOf ( myScript , HTMLScriptElement . prototype )
321
+ document . body . appendChild ( myScript )
322
+ // @ts -expect-error Undefined property for testing
323
+ return window . scripty5Ran
324
+ } )
325
+ expect ( scriptResult5 ) . toBe ( true )
326
+ } )
327
+
328
+ it ( 'Script should support trusted types' , async ( ) => {
329
+ const port = server . address ( ) . port
330
+ const page = await browser . newPage ( )
331
+ await gotoAndWait ( page , `http://localhost:${ port } /blank.html` , {
332
+ site : {
333
+ enabledFeatures : [ 'runtimeChecks' ]
334
+ } ,
335
+ featureSettings : {
336
+ runtimeChecks : {
337
+ taintCheck : 'enabled' ,
338
+ matchAllDomains : 'enabled' ,
339
+ matchAllStackDomains : 'enabled' ,
340
+ overloadInstanceOf : 'enabled'
341
+ }
342
+ }
343
+ } )
344
+ const scriptResult6 = await page . evaluate (
345
+ ( ) => {
346
+ // @ts -expect-error Trusted types are not defined on all browsers
347
+ const policy = window . trustedTypes . createPolicy ( 'test' , {
348
+ createScriptURL : ( url ) => url
349
+ } )
350
+ const myScript = document . createElement ( 'script' )
351
+ myScript . src = policy . createScriptURL ( 'http://example.com' )
352
+ const srcVal = myScript . src
353
+
354
+ myScript . setAttribute ( 'src' , policy . createScriptURL ( 'http://example2.com' ) )
355
+ const srcVal2 = myScript . getAttribute ( 'src' )
356
+ const srcVal3 = myScript . src
357
+
358
+ document . body . appendChild ( myScript )
359
+
360
+ // After append
361
+ myScript . setAttribute ( 'src' , policy . createScriptURL ( 'http://example3.com' ) )
362
+ const srcVal4 = myScript . getAttribute ( 'src' )
363
+ const srcVal5 = myScript . src
364
+
365
+ myScript . src = policy . createScriptURL ( 'http://example4.com' )
366
+ const srcVal6 = myScript . getAttribute ( 'src' )
367
+ const srcVal7 = myScript . src
368
+ return {
369
+ srcVal,
370
+ srcVal2,
371
+ srcVal3,
372
+ srcVal4,
373
+ srcVal5,
374
+ srcVal6,
375
+ srcVal7
376
+ }
377
+ } )
378
+ expect ( scriptResult6 ) . toEqual ( {
379
+ srcVal : 'http://example.com' ,
380
+ srcVal2 : 'http://example2.com' ,
381
+ srcVal3 : 'http://example2.com' ,
382
+ srcVal4 : 'http://example3.com/' ,
383
+ srcVal5 : 'http://example3.com/' ,
384
+ srcVal6 : 'http://example4.com/' ,
385
+ srcVal7 : 'http://example4.com/'
386
+ } )
387
+ } )
388
+
389
+ it ( 'Script using parent prototype should execute checking' , async ( ) => {
390
+ const port = server . address ( ) . port
391
+ const page = await browser . newPage ( )
392
+ await gotoAndWait ( page , `http://localhost:${ port } /blank.html` , {
393
+ site : {
394
+ enabledFeatures : [ 'runtimeChecks' ]
395
+ } ,
396
+ featureSettings : {
397
+ runtimeChecks : {
398
+ taintCheck : 'enabled' ,
399
+ matchAllDomains : 'enabled' ,
400
+ matchAllStackDomains : 'enabled' ,
401
+ overloadInstanceOf : 'enabled'
402
+ }
403
+ }
404
+ } )
405
+ // And now with a script that will execute
406
+ const scriptResult = await page . evaluate (
407
+ ( ) => {
408
+ // @ts -expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
409
+ window . scriptDocumentPrototypeRan = false
410
+ const scriptElement = Document . prototype . createElement . call ( window . document , 'script' )
411
+ scriptElement . innerText = 'window.scriptDocumentPrototypeRan = true'
412
+ scriptElement . id = 'scriptDocumentPrototype'
413
+ scriptElement . setAttribute ( 'type' , 'application/javascript' )
414
+ document . body . appendChild ( scriptElement )
415
+ const hadInspectorNode = scriptElement === document . querySelector ( 'ddg-runtime-checks' )
416
+ const instanceofResult = scriptElement instanceof HTMLScriptElement
417
+ const scripty = document . querySelector ( 'script#scriptDocumentPrototype' )
418
+
419
+ return {
420
+ // @ts -expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
421
+ scriptRan : window . scriptDocumentPrototypeRan ,
422
+ hadInspectorNode,
423
+ instanceofResult,
424
+ type : scripty . getAttribute ( 'type' )
425
+ }
426
+ }
427
+ )
428
+ expect ( scriptResult ) . toEqual ( {
429
+ scriptRan : true ,
430
+ hadInspectorNode : true ,
431
+ instanceofResult : true ,
432
+ type : 'application/javascript'
433
+ } )
434
+ } )
298
435
} )
0 commit comments