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 df33f0766607..cc052a66bf06 100644
--- a/packages/angular/build/src/utils/index-file/auto-csp.ts
+++ b/packages/angular/build/src/utils/index-file/auto-csp.ts
@@ -270,8 +270,10 @@ function createLoaderScript(srcList: SrcScriptTag[], enableTrustedTypes = false)
.map((s) => {
// URI encoding means value can't escape string, JS, or HTML context.
const srcAttr = encodeURI(s.src).replaceAll("'", "\\'");
- // Can only be 'module' or a JS MIME type or an empty string.
- const typeAttr = s.type ? "'" + s.type + "'" : "''";
+ // 'module', a JS MIME type, or an empty string. A JS MIME type may carry
+ // parameters after a ';', which isJavascriptMimeType() does not constrain,
+ // so encode this the same way as integrity and crossOrigin below.
+ const typeAttr = JSON.stringify(s.type ?? '').replaceAll('<', '\\u003c');
const asyncAttr = !!s.async;
const deferAttr = !!s.defer;
const integrityAttr = JSON.stringify(s.integrity ?? null).replaceAll('<', '\\u003c');
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 29e9bff68074..333a78294567 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
@@ -58,7 +58,7 @@ describe('auto-csp', () => {
const csps = getCsps(result);
expect(csps).toHaveSize(1);
expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX);
- expect(result).toContain(`const scripts = [['./main.js', '', false, false, null, null]];`);
+ expect(result).toContain(`const scripts = [['./main.js', "", false, false, null, null]];`);
});
it('should rewrite a single source script in place', async () => {
@@ -78,7 +78,7 @@ describe('auto-csp', () => {
expect(csps[0]).toMatch(CSP_SINGLE_HASH_REGEX);
// Our loader script appears after the HTML text content.
expect(result).toMatch(
- /Some text<\/div>\s*`);
@@ -166,12 +166,12 @@ describe('auto-csp', () => {
// Loader script for main.js and main2.js appear after 'foo' and before 'bar'.
expect(result).toMatch(
// eslint-disable-next-line max-len
- /console.log\('foo'\);<\/script>\s*
+