fix(@angular/build): encode script type in auto-CSP loader - #34035
Open
yoggydev wants to merge 1 commit into
Open
fix(@angular/build): encode script type in auto-CSP loader#34035yoggydev wants to merge 1 commit into
yoggydev wants to merge 1 commit into
Conversation
createLoaderScript() interpolates four script attributes into the generated loader. integrity and crossOrigin are encoded with JSON.stringify and \u003c, but type is inserted directly into a single-quoted JavaScript string literal. The comment above the function states that type can only be 'module', a JS MIME type or an empty string, but isJavascriptMimeType() only compares the part before the first ';', so a value such as text/javascript;<parameters> reaches the loader unchanged. A quote in that value closes the string literal, and a closing script tag terminates the generated element. Encode type the same way as its neighbours. Both branches of createLoaderScript() share srcListFormatted, so one change covers Trusted Types enabled and disabled.
There was a problem hiding this comment.
Code Review
This pull request updates the auto-csp utility to safely encode the script type attribute using JSON.stringify and escaping < characters. This prevents potential script injection or context escaping when a script type contains MIME parameters or HTML tags. The corresponding unit tests have been updated to reflect the double-quoted output, and new tests have been added to verify the encoding of MIME parameters and closing script tags. There are no review comments, so no further feedback is provided.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
Please check to confirm your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
createLoaderScript()in the auto-CSP generator interpolates four<script>attributesinto the generated loader source. Three are encoded;
typeis not:The comment above the function gives the reason it is safe to interpolate
typedirectly:That does not match the check the value actually passes. The gate is
isJavascriptMimeType():Only the part before the first
;is compared — correctly, since that mirrors how a browsermatches a script's MIME essence — so a value such as
type="text/javascript;<parameters>"passes the gate and reaches
typeAttrunchanged.typeis validated for the purpose ofdeciding whether a script should be dynamically loaded, and then embedded into a JavaScript
string literal as though that validation had also constrained its characters.
Two consequences follow from
index.htmlcontent alone:'in the value closes the string literal, so the rest of the attribute becomesstatements in the loader source. The generated loader is hashed into the emitted CSP, so
such statements become part of the policy's trusted script hash.
</script>in the value terminates the generated element, because the loader is writtenwith
rewriter.emitRaw(...). The.replaceAll('<', '\\u003c')on the two neighbouringattributes exists to prevent exactly this.
What is the new behavior?
typeis encoded the same way asintegrityandcrossOrigin:Both branches of
createLoaderScript()(Trusted Types enabled and disabled) share the samesrcListFormatted, so this single change covers both.Two specs are added, one per case above. Existing specs that spell out the loader tuple are
updated for the quote style
JSON.stringifyproduces (''becomes"").Does this PR introduce a breaking change?
The only observable difference is the quote style of the
typeslot in the generated loader,which is internal to the emitted script.
Other information
This is a defense-in-depth change. I was not able to identify an attacker-controlled path to
the
typeattribute that does not already require control over the application's build input:autoCsp()is reached only fromtools/esbuild/index-html-generator.ts, once per build, overindex.html, and the<script>tags the CLI generates itself carry a literaltype="module"(
augment-index-html.ts). Filing it as an ordinary fix for that reason.