File tree Expand file tree Collapse file tree
packages/angular/build/src/utils/index-file Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -233,4 +233,31 @@ describe('inlineCriticalCss', () => {
233233 expect ( warnings . length ) . toBeGreaterThan ( 0 ) ;
234234 expect ( warnings [ 0 ] ) . toContain ( 'missing.css' ) ;
235235 } ) ;
236+
237+ it ( 'should retain nonce on stylesheet links and noscript fallback' , async ( ) => {
238+ const initialContent = `
239+ <html>
240+ <head>
241+ <link href="styles.css" rel="stylesheet" nonce="test-nonce">
242+ </head>
243+ <body></body>
244+ </html>` ;
245+
246+ const { content, errors, warnings } = await inlineCriticalCss (
247+ initialContent ,
248+ '/dist/' ,
249+ undefined ,
250+ false ,
251+ readAsset ,
252+ ) ;
253+
254+ expect ( errors ) . toEqual ( [ ] ) ;
255+ expect ( warnings ) . toEqual ( [ ] ) ;
256+ expect ( content ) . toContain (
257+ '<link href="styles.css" rel="stylesheet" nonce="test-nonce" media="print" data-beasties-media="all">' ,
258+ ) ;
259+ expect ( content ) . toContain (
260+ '<noscript><link href="styles.css" rel="stylesheet" nonce="test-nonce"></noscript>' ,
261+ ) ;
262+ } ) ;
236263} ) ;
Original file line number Diff line number Diff line change @@ -28,11 +28,26 @@ export async function addNonce(html: string): Promise<string> {
2828 const { rewriter, transformedContent } = await htmlRewritingStream ( html ) ;
2929
3030 rewriter . on ( 'startTag' , ( tag ) => {
31- if (
32- ( tag . tagName === 'style' || tag . tagName === 'script' ) &&
33- ! tag . attrs . some ( ( attr ) => attr . name === 'nonce' )
34- ) {
35- tag . attrs . push ( { name : 'nonce' , value : nonce } ) ;
31+ const { tagName, attrs } = tag ;
32+
33+ if ( tagName === 'style' || tagName === 'script' || tagName === 'link' ) {
34+ let isTarget = tagName !== 'link' ;
35+ let hasNonce = false ;
36+
37+ for ( const attr of attrs ) {
38+ if ( attr . name === 'nonce' ) {
39+ hasNonce = true ;
40+ } else if ( tagName === 'link' && attr . name === 'rel' && attr . value ) {
41+ const tokens = attr . value . trim ( ) . split ( / \s + / ) ;
42+ if ( tokens . includes ( 'stylesheet' ) || tokens . includes ( 'modulepreload' ) ) {
43+ isTarget = true ;
44+ }
45+ }
46+ }
47+
48+ if ( isTarget && ! hasNonce ) {
49+ attrs . push ( { name : 'nonce' , value : nonce } ) ;
50+ }
3651 }
3752
3853 rewriter . emitStartTag ( tag ) ;
Original file line number Diff line number Diff line change @@ -92,4 +92,21 @@ describe('addNonce', () => {
9292 expect ( result ) . toContain ( '<script src="./main.js" nonce="{% nonce %}"></script>' ) ;
9393 expect ( result ) . toContain ( `<script nonce="{% nonce %}">console.log('bar');</script>` ) ;
9494 } ) ;
95+
96+ it ( 'should add the nonce expression to stylesheet link tags' , async ( ) => {
97+ const result = await addNonce ( `
98+ <html>
99+ <head>
100+ <link rel="stylesheet" href="styles.css">
101+ <link rel="preload" href="font.woff2" as="font">
102+ </head>
103+ <body>
104+ <app ngCspNonce="{% nonce %}"></app>
105+ </body>
106+ </html>
107+ ` ) ;
108+
109+ expect ( result ) . toContain ( '<link rel="stylesheet" href="styles.css" nonce="{% nonce %}">' ) ;
110+ expect ( result ) . toContain ( '<link rel="preload" href="font.woff2" as="font">' ) ;
111+ } ) ;
95112} ) ;
You can’t perform that action at this time.
0 commit comments