diff --git a/package.json b/package.json
index dc62e62745d3..3e64f944dd9b 100644
--- a/package.json
+++ b/package.json
@@ -174,6 +174,7 @@
"ora": "5.4.1",
"pacote": "19.0.0",
"parse5-html-rewriting-stream": "7.0.0",
+ "parse5-sax-parser": "7.0.0",
"picomatch": "4.0.2",
"piscina": "4.7.0",
"postcss": "8.4.47",
diff --git a/packages/angular/build/BUILD.bazel b/packages/angular/build/BUILD.bazel
index 45a284740a07..00ca5da92448 100644
--- a/packages/angular/build/BUILD.bazel
+++ b/packages/angular/build/BUILD.bazel
@@ -89,6 +89,7 @@ ts_library(
"@npm//magic-string",
"@npm//mrmime",
"@npm//parse5-html-rewriting-stream",
+ "@npm//parse5-sax-parser",
"@npm//picomatch",
"@npm//piscina",
"@npm//postcss",
diff --git a/packages/angular/build/src/utils/index-file/auto-csp.ts b/packages/angular/build/src/utils/index-file/auto-csp.ts
new file mode 100644
index 000000000000..54db86a1f37b
--- /dev/null
+++ b/packages/angular/build/src/utils/index-file/auto-csp.ts
@@ -0,0 +1,252 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.dev/license
+ */
+
+import { htmlRewritingStream } from './html-rewriting-stream';
+import { StartTag } from 'parse5-sax-parser';
+import * as crypto from 'crypto';
+
+/**
+ * The hash function to use for hash directives to use in the CSP.
+ */
+const HASH_FUNCTION = 'sha256';
+
+/**
+ * Store the appropriate attributes of a sourced script tag to generate the loader script.
+ */
+interface SrcScriptTag {
+ scriptType: 'src';
+ src: string;
+ type?: string;
+ async?: boolean;
+}
+
+/**
+ * Get the specified attribute or return undefined if the tag doesn't have that attribute.
+ *
+ * @param tag StartTag of the `);
+ }
+ scriptContent = undefined;
+ }
+ rewriter.emitStartTag(tag);
+ });
+
+ rewriter.on('text', (tag, html) => {
+ if (openedScriptTag && !getScriptAttributeValue(openedScriptTag, 'src')) {
+ hashes.push(hashInlineScript(html));
+ }
+ rewriter.emitText(tag);
+ });
+
+ rewriter.on('endTag', (tag, html) => {
+ if (tag.tagName === 'script') {
+ const src = getScriptAttributeValue(openedScriptTag!, 'src');
+ openedScriptTag = undefined;
+
+ if (src) {
+ return;
+ }
+ }
+
+ if (tag.tagName === 'body' || tag.tagName === 'html') {
+ // Write the loader script if a string of `);
+ }
+ scriptContent = undefined;
+ }
+ }
+ rewriter.emitEndTag(tag);
+ });
+
+ const rewritten = await transformedContent();
+
+ // Second pass to add the header
+ const secondPass = await htmlRewritingStream(rewritten);
+ secondPass.rewriter.on('endTag', (tag, _) => {
+ if (tag.tagName === 'head') {
+ // See what hashes we came up with!
+ secondPass.rewriter.emitRaw(
+ ``,
+ );
+ }
+ secondPass.rewriter.emitEndTag(tag);
+ });
+ return secondPass.transformedContent();
+}
+
+/**
+ * Returns a strict Content Security Policy for mittigating XSS.
+ * For more details read csp.withgoogle.com.
+ * If you modify this CSP, make sure it has not become trivially bypassable by
+ * checking the policy using csp-evaluator.withgoogle.com.
+ *
+ * @param hashes A list of sha-256 hashes of trusted inline scripts.
+ * @param enableTrustedTypes If Trusted Types should be enabled for scripts.
+ * @param enableBrowserFallbacks If fallbacks for older browsers should be
+ * added. This is will not weaken the policy as modern browsers will ignore
+ * the fallbacks.
+ * @param enableUnsafeEval If you cannot remove all uses of eval(), you can
+ * still set a strict CSP, but you will have to use the 'unsafe-eval'
+ * keyword which will make your policy slightly less secure.
+ */
+function getStrictCsp(
+ hashes?: string[],
+ // default CSP options
+ cspOptions: {
+ enableBrowserFallbacks?: boolean;
+ enableTrustedTypes?: boolean;
+ enableUnsafeEval?: boolean;
+ } = {
+ enableBrowserFallbacks: true,
+ enableTrustedTypes: false,
+ enableUnsafeEval: false,
+ },
+): string {
+ hashes = hashes || [];
+ let strictCspTemplate = {
+ // 'strict-dynamic' allows hashed scripts to create new scripts.
+ 'script-src': [`'strict-dynamic'`, ...hashes],
+ // Restricts `object-src` to disable dangerous plugins like Flash.
+ 'object-src': [`'none'`],
+ // Restricts `base-uri` to block the injection of `