Skip to content

Commit 464db37

Browse files
committed
Weird corner-case URLs that can escape/break our loader script.
1 parent a414ef5 commit 464db37

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

packages/angular/build/src/utils/index-file/auto-csp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ function createLoaderScript(srcList: SrcScriptTag[], enableTrustedTypes = false)
280280
const srcListFormatted = srcList
281281
.map(
282282
(s) =>
283-
`['${encodeURI(s.src)}', ${s.type ? "'" + encodeURI(s.type) + "'" : undefined}, ${s.async ? 'true' : 'false'}, ${s.defer ? 'true' : 'false'}]`,
283+
`['${encodeURI(s.src).replaceAll("'", "\\'")}', ${s.type ? "'" + encodeURI(s.type) + "'" : undefined}, ${s.async ? 'true' : 'false'}, ${s.defer ? 'true' : 'false'}]`,
284284
)
285285
.join();
286286
return enableTrustedTypes

packages/angular/build/src/utils/index-file/auto-csp_spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,35 @@ describe('auto-csp', () => {
104104
expect(Array.from(result.matchAll(/\<script\>/g)).length).toEqual(1);
105105
});
106106

107+
it('should rewrite source scripts with weird URLs', async () => {
108+
const result = await autoCsp(`
109+
<html>
110+
<head>
111+
</head>
112+
<body>
113+
<script src="/foo&amp;bar"></script>
114+
<script src="/one'two\\'three\\\\'four\\\\\\'five"></script>
115+
<script src="/one&two&amp;three&amp;amp;four"></script>
116+
<script src="./</script>"></script>
117+
<div>Some text </div>
118+
</body>
119+
</html>
120+
`);
121+
122+
const csps = getCsps(result);
123+
expect(csps.length).toBe(1);
124+
expect(csps[0]).toMatch(ONE_HASH_CSP);
125+
// &amp; encodes correctly
126+
expect(result).toContain(`'/foo&bar'`);
127+
// Impossible to escape a string and create invalid loader JS with a '
128+
// (Quotes and backslashes work)
129+
expect(result).toContain(`'/one\\'two%5C\\'three%5C%5C\\'four%5C%5C%5C\\'five'`);
130+
// HTML entities work
131+
expect(result).toContain(`'/one&two&three&amp;four'`);
132+
// Cannot escape JS context to HTML
133+
expect(result).toContain(`'./%3C/script%3E'`);
134+
});
135+
107136
it('should rewrite all script tags', async () => {
108137
const result = await autoCsp(`
109138
<html>

0 commit comments

Comments
 (0)