From e7e43d6db5e6db05ab3d4cc677919d4554194e80 Mon Sep 17 00:00:00 2001 From: Aaron Shim Date: Thu, 17 Oct 2024 16:17:02 +0000 Subject: [PATCH] Weird corner-case URLs that can escape/break our loader script. --- .../build/src/utils/index-file/auto-csp.ts | 2 +- .../src/utils/index-file/auto-csp_spec.ts | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/angular/build/src/utils/index-file/auto-csp.ts b/packages/angular/build/src/utils/index-file/auto-csp.ts index cc93aec73609..5437a6c7a2e6 100644 --- a/packages/angular/build/src/utils/index-file/auto-csp.ts +++ b/packages/angular/build/src/utils/index-file/auto-csp.ts @@ -280,7 +280,7 @@ function createLoaderScript(srcList: SrcScriptTag[], enableTrustedTypes = false) const srcListFormatted = srcList .map( (s) => - `['${encodeURI(s.src)}', ${s.type ? "'" + encodeURI(s.type) + "'" : undefined}, ${s.async ? 'true' : 'false'}, ${s.defer ? 'true' : 'false'}]`, + `['${encodeURI(s.src).replaceAll("'", "\\'")}', ${s.type ? "'" + encodeURI(s.type) + "'" : undefined}, ${s.async ? 'true' : 'false'}, ${s.defer ? 'true' : 'false'}]`, ) .join(); return enableTrustedTypes diff --git a/packages/angular/build/src/utils/index-file/auto-csp_spec.ts b/packages/angular/build/src/utils/index-file/auto-csp_spec.ts index a2c4b875eb31..4d5626fc4714 100644 --- a/packages/angular/build/src/utils/index-file/auto-csp_spec.ts +++ b/packages/angular/build/src/utils/index-file/auto-csp_spec.ts @@ -104,6 +104,35 @@ describe('auto-csp', () => { expect(Array.from(result.matchAll(/\/g)).length).toEqual(1); }); + it('should rewrite source scripts with weird URLs', async () => { + const result = await autoCsp(` + + + + + + + + +
Some text
+ + + `); + + const csps = getCsps(result); + expect(csps.length).toBe(1); + expect(csps[0]).toMatch(ONE_HASH_CSP); + // & encodes correctly + expect(result).toContain(`'/foo&bar'`); + // Impossible to escape a string and create invalid loader JS with a ' + // (Quotes and backslashes work) + expect(result).toContain(`'/one\\'two%5C\\'three%5C%5C\\'four%5C%5C%5C\\'five'`); + // HTML entities work + expect(result).toContain(`'/one&two&three&four'`); + // Cannot escape JS context to HTML + expect(result).toContain(`'./%3C/script%3E'`); + }); + it('should rewrite all script tags', async () => { const result = await autoCsp(`