Skip to content

Commit

Permalink
Options get plumbed through to the builder.
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronshim committed Oct 17, 2024
1 parent 7551f76 commit 7c92fa8
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 7 deletions.
2 changes: 2 additions & 0 deletions packages/angular/build/src/builders/application/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export async function normalizeOptions(
partialSSRBuild = false,
externalRuntimeStyles,
instrumentForCoverage,
security,
} = options;

// Return all the normalized options
Expand Down Expand Up @@ -461,6 +462,7 @@ export async function normalizeOptions(
partialSSRBuild: usePartialSsrBuild || partialSSRBuild,
externalRuntimeStyles,
instrumentForCoverage,
security,
};
}

Expand Down
27 changes: 27 additions & 0 deletions packages/angular/build/src/builders/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,33 @@
"type": "string",
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"security": {
"description": "Security features to protect against XSS and other common attacks",
"type": "object",
"additionalProperties": false,
"properties": {
"autoCsp": {
"description": "Enables auto-CSP generation. Will default to true once we are out of experimental/preview phases.",
"default": false,
"oneOf": [
{
"type": "object",
"properties": {
"unsafeEval": {
"type": "boolean",
"description": "Include the `unsafe-eval` directive in the auto-CSP. Please only enable this if you are absolutely sure that you need to, as allowing calls to eval will weaken the XSS defenses provided by the auto-CSP.",
"default": false
}
},
"additionalProperties": false
},
{
"type": "boolean"
}
]
}
}
},
"scripts": {
"description": "Global scripts to be included in the build.",
"type": "array",
Expand Down
11 changes: 10 additions & 1 deletion packages/angular/build/src/tools/esbuild/index-html-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ export async function generateIndexHtml(
throw new Error(`Output file does not exist: ${relativefilePath}`);
};

// Read the Auto CSP options.
const autoCsp = buildOptions.security?.autoCsp;
const autoCspOptions =
autoCsp === true
? { unsafeEval: false }
: autoCsp
? { unsafeEval: !!autoCsp.unsafeEval }
: undefined;

// Create an index HTML generator that reads from the in-memory output files
const indexHtmlGenerator = new IndexHtmlGenerator({
indexPath: indexHtmlOptions.input,
Expand All @@ -94,7 +103,7 @@ export async function generateIndexHtml(
buildOptions.prerenderOptions ||
buildOptions.appShellOptions
),
autoCsp: true,
autoCsp: autoCspOptions,
});

indexHtmlGenerator.readAsset = readAsset;
Expand Down
8 changes: 6 additions & 2 deletions packages/angular/build/src/utils/index-file/auto-csp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function hashTextContent(scriptText: string): string {
* @param html Markup that should be processed.
* @returns The transformed HTML that contains the `<meta>` tag CSP and dynamic loader scripts.
*/
export async function autoCsp(html: string): Promise<string> {
export async function autoCsp(html: string, unsafeEval = false): Promise<string> {
const { rewriter, transformedContent } = await htmlRewritingStream(html);

let openedScriptTag: StartTag | undefined = undefined;
Expand Down Expand Up @@ -190,7 +190,11 @@ export async function autoCsp(html: string): Promise<string> {
if (tag.tagName === 'head') {
// See what hashes we came up with!
secondPass.rewriter.emitRaw(
`<meta http-equiv="Content-Security-Policy" content="${getStrictCsp(hashes)}">`,
`<meta http-equiv="Content-Security-Policy" content="${getStrictCsp(hashes, {
enableBrowserFallbacks: true,
enableTrustedTypes: false,
enableUnsafeEval: unsafeEval,
})}">`,
);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export interface IndexHtmlGeneratorProcessOptions {
hints?: { url: string; mode: HintMode; as?: string }[];
}

export interface AutoCspOptions {
unsafeEval: boolean;
}

export interface IndexHtmlGeneratorOptions {
indexPath: string;
deployUrl?: string;
Expand All @@ -44,7 +48,7 @@ export interface IndexHtmlGeneratorOptions {
cache?: NormalizedCachedOptions;
imageDomains?: string[];
generateDedicatedSSRContent?: boolean;
autoCsp?: boolean;
autoCsp?: AutoCspOptions;
}

export type IndexHtmlTransform = (content: string) => Promise<string>;
Expand Down Expand Up @@ -91,7 +95,7 @@ export class IndexHtmlGenerator {

// Auto-CSP (as the last step)
if (options.autoCsp) {
this.csrPlugins.push(autoCspPlugin());
this.csrPlugins.push(autoCspPlugin(options.autoCsp.unsafeEval));
}
}

Expand Down Expand Up @@ -205,8 +209,8 @@ function addNoncePlugin(): IndexHtmlGeneratorPlugin {
return (html) => addNonce(html);
}

function autoCspPlugin(): IndexHtmlGeneratorPlugin {
return (html) => autoCsp(html);
function autoCspPlugin(unsafeEval: boolean): IndexHtmlGeneratorPlugin {
return (html) => autoCsp(html, unsafeEval);
}

function postTransformPlugin({ options }: IndexHtmlGenerator): IndexHtmlGeneratorPlugin {
Expand Down

0 comments on commit 7c92fa8

Please sign in to comment.