@@ -58,7 +58,7 @@ describe('auto-csp', () => {
5858 const csps = getCsps ( result ) ;
5959 expect ( csps ) . toHaveSize ( 1 ) ;
6060 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
61- expect ( result ) . toContain ( `const scripts = [['./main.js', '' , false, false, null, null]];` ) ;
61+ expect ( result ) . toContain ( `const scripts = [['./main.js', "" , false, false, null, null]];` ) ;
6262 } ) ;
6363
6464 it ( 'should rewrite a single source script in place' , async ( ) => {
@@ -78,7 +78,7 @@ describe('auto-csp', () => {
7878 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
7979 // Our loader script appears after the HTML text content.
8080 expect ( result ) . toMatch (
81- / S o m e t e x t < \/ d i v > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n .j s ' , ' ' , f a l s e , f a l s e , n u l l , n u l l \] \] ; / ,
81+ / S o m e t e x t < \/ d i v > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n .j s ' , " " , f a l s e , f a l s e , n u l l , n u l l \] \] ; / ,
8282 ) ;
8383 } ) ;
8484
@@ -103,7 +103,7 @@ describe('auto-csp', () => {
103103 expect ( csps [ 0 ] ) . toMatch ( CSP_TWO_HASHES_REGEX ) ;
104104 expect ( result ) . toContain (
105105 // eslint-disable-next-line max-len
106- `const scripts = [['./main1.js', '' , false, false, null, null],['./main2.js', '' , true, false, null, null],['./main3.js', ' module' , true, true, null, null]];` ,
106+ `const scripts = [['./main1.js', "" , false, false, null, null],['./main2.js', "" , true, false, null, null],['./main3.js', " module" , true, true, null, null]];` ,
107107 ) ;
108108 // Head loader script is in the head.
109109 expect ( result ) . toContain ( `</script></head>` ) ;
@@ -166,12 +166,12 @@ describe('auto-csp', () => {
166166 // Loader script for main.js and main2.js appear after 'foo' and before 'bar'.
167167 expect ( result ) . toMatch (
168168 // eslint-disable-next-line max-len
169- / c o n s o l e .l o g \( ' f o o ' \) ; < \/ s c r i p t > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n .j s ' , ' ' , f a l s e , f a l s e , n u l l , n u l l \] , \[ ' .\/ m a i n 2 .j s ' , ' ' , f a l s e , f a l s e , n u l l , n u l l \] \] ; [ \s \S ] * c o n s o l e .l o g \( ' b a r ' \) ; / ,
169+ / c o n s o l e .l o g \( ' f o o ' \) ; < \/ s c r i p t > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n .j s ' , " " , f a l s e , f a l s e , n u l l , n u l l \] , \[ ' .\/ m a i n 2 .j s ' , " " , f a l s e , f a l s e , n u l l , n u l l \] \] ; [ \s \S ] * c o n s o l e .l o g \( ' b a r ' \) ; / ,
170170 ) ;
171171 // Loader script for main3.js and main4.js appear after 'bar'.
172172 expect ( result ) . toMatch (
173173 // eslint-disable-next-line max-len
174- / c o n s o l e .l o g \( ' b a r ' \) ; < \/ s c r i p t > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n 3 .j s ' , ' ' , f a l s e , f a l s e , n u l l , n u l l \] , \[ ' .\/ m a i n 4 .j s ' , ' ' , f a l s e , f a l s e , n u l l , n u l l \] \] ; / ,
174+ / c o n s o l e .l o g \( ' b a r ' \) ; < \/ s c r i p t > \s * < s c r i p t > \( \( \) = > { \s * c o n s t s c r i p t s = \[ \[ ' .\/ m a i n 3 .j s ' , " " , f a l s e , f a l s e , n u l l , n u l l \] , \[ ' .\/ m a i n 4 .j s ' , " " , f a l s e , f a l s e , n u l l , n u l l \] \] ; / ,
175175 ) ;
176176 // Exactly 4 scripts should be left.
177177 expect ( Array . from ( result . matchAll ( / < s c r i p t > / gi) ) . length ) . toEqual ( 4 ) ;
@@ -238,7 +238,7 @@ describe('auto-csp', () => {
238238 expect ( csps ) . toHaveSize ( 1 ) ;
239239 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
240240 expect ( result ) . toContain (
241- `const scripts = [['./main.js', ' module' , false, false, "sha384-xyz123", "anonymous"]];` ,
241+ `const scripts = [['./main.js', " module" , false, false, "sha384-xyz123", "anonymous"]];` ,
242242 ) ;
243243 } ) ;
244244
@@ -258,7 +258,7 @@ describe('auto-csp', () => {
258258 expect ( csps ) . toHaveSize ( 1 ) ;
259259 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
260260 expect ( result ) . toContain (
261- `const scripts = [['./main.js', '' , false, false, "sha384-xyz123", null]];` ,
261+ `const scripts = [['./main.js', "" , false, false, "sha384-xyz123", null]];` ,
262262 ) ;
263263 } ) ;
264264
@@ -278,7 +278,7 @@ describe('auto-csp', () => {
278278 expect ( csps ) . toHaveSize ( 1 ) ;
279279 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
280280 expect ( result ) . toContain (
281- `const scripts = [['./main.js', '' , false, false, null, "anonymous"]];` ,
281+ `const scripts = [['./main.js', "" , false, false, null, "anonymous"]];` ,
282282 ) ;
283283 } ) ;
284284
@@ -296,7 +296,7 @@ describe('auto-csp', () => {
296296 expect ( csps ) . toHaveSize ( 1 ) ;
297297 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
298298 expect ( result ) . toContain (
299- `const scripts = [['./main.js', ' application/javascript' , false, false, null, null]];` ,
299+ `const scripts = [['./main.js', " application/javascript" , false, false, null, null]];` ,
300300 ) ;
301301 } ) ;
302302
@@ -314,7 +314,7 @@ describe('auto-csp', () => {
314314 expect ( csps ) . toHaveSize ( 1 ) ;
315315 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
316316 expect ( result ) . toContain (
317- `const scripts = [['./main.js', ' Text/JavaScript ; charset=utf-8' , false, false, null, null]];` ,
317+ `const scripts = [['./main.js', " Text/JavaScript ; charset=utf-8" , false, false, null, null]];` ,
318318 ) ;
319319 } ) ;
320320
@@ -332,7 +332,7 @@ describe('auto-csp', () => {
332332 expect ( csps ) . toHaveSize ( 1 ) ;
333333 expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
334334 expect ( result ) . toContain (
335- `const scripts = [['./main.js', ' Module' , false, false, null, null]];` ,
335+ `const scripts = [['./main.js', " Module" , false, false, null, null]];` ,
336336 ) ;
337337 } ) ;
338338
@@ -351,6 +351,44 @@ describe('auto-csp', () => {
351351 expect ( result ) . not . toContain ( 'const scripts =' ) ;
352352 } ) ;
353353
354+ it ( 'should encode a script type that carries MIME parameters' , async ( ) => {
355+ const result = await autoCsp ( `
356+ <html>
357+ <head>
358+ </head>
359+ <body>
360+ <script src="./main.js" type="text/javascript;']];var x=1;var junk=[['a','b"></script>
361+ </body>
362+ </html>
363+ ` ) ;
364+
365+ const csps = getCsps ( result ) ;
366+ expect ( csps ) . toHaveSize ( 1 ) ;
367+ expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
368+ // The type stays inside its string literal.
369+ expect ( result ) . toContain (
370+ `const scripts = [['./main.js', "text/javascript;']];var x=1;var junk=[['a','b", false, false, null, null]];` ,
371+ ) ;
372+ } ) ;
373+
374+ it ( 'should encode a script type that contains a closing script tag' , async ( ) => {
375+ const result = await autoCsp ( `
376+ <html>
377+ <head>
378+ </head>
379+ <body>
380+ <script src="./main.js" type="text/javascript;</script><script>x</script>"></script>
381+ </body>
382+ </html>
383+ ` ) ;
384+
385+ const csps = getCsps ( result ) ;
386+ expect ( csps ) . toHaveSize ( 1 ) ;
387+ expect ( csps [ 0 ] ) . toMatch ( CSP_SINGLE_HASH_REGEX ) ;
388+ // Only the loader element is emitted.
389+ expect ( Array . from ( result . matchAll ( / < s c r i p t / gi) ) . length ) . toEqual ( 1 ) ;
390+ } ) ;
391+
354392 describe ( 'isJavascriptMimeType' , ( ) => {
355393 it ( 'should identify standard JavaScript MIME types' , ( ) => {
356394 expect ( isJavascriptMimeType ( 'text/javascript' ) ) . toBeTrue ( ) ;
0 commit comments