Skip to content

Commit eccdeae

Browse files
MeAkibalan-agius4
andcommitted
docs: add CSP guidance for static hosting and CDN caching
Fixes angular#70877 Co-authored-by: Alan Agius <alan.agius4@gmail.com>
1 parent 344b10f commit eccdeae

1 file changed

Lines changed: 53 additions & 7 deletions

File tree

‎adev/src/content/guide/security.md‎

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ When serving your Angular application, the server should include a randomly-gene
150150
You must provide this nonce to Angular so that the framework can render `<style>` elements.
151151
You can set the nonce for Angular in one of the following ways:
152152

153-
1. Set the `autoCsp` option to `true` in the [workspace configuration](reference/configs/workspace-config#extra-build-and-test-options).
154153
1. Set the `ngCspNonce` attribute on the root application element as `<app ngCspNonce="randomNonceGoesHere"></app>`. Use this approach if you have access to server-side templating that can add the nonce both to the header and the `index.html` when constructing the response.
155154
1. Provide the nonce using the `CSP_NONCE` injection token. Use this approach if you have access to the nonce at runtime and you want to be able to cache the `index.html`.
156155

@@ -180,19 +179,66 @@ To maintain the "one-time-use" integrity of a nonce, it should ideally be genera
180179

181180
</docs-callout>
182181

183-
NOTE: If you want to [inline the critical CSS](/tools/cli/build#critical-css-inlining) of your application, you can not use the `CSP_NONCE` token, and should prefer the `autoCsp` option or set the `ngCspNonce` attribute on the root application element.
182+
NOTE: If you want to [inline the critical CSS](/tools/cli/build#critical-css-inlining) of your application, you can not use the `CSP_NONCE` token, and should prefer the `security.autoCsp` option in the [workspace configuration](reference/configs/workspace-config#extra-build-and-test-options) or set the `ngCspNonce` attribute on the root application element.
184183

185184
If you cannot generate nonces in your project, you can allow inline styles by adding `'unsafe-inline'` to the `style-src` section of the CSP header.
186185

187-
| Sections | Details |
188-
| :----------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
189-
| `default-src 'self';` | Allows the page to load all its required resources from the same origin. |
190-
| `style-src 'self' 'nonce-randomNonceGoesHere';` | Allows the page to load global styles from the same origin \(`'self'`\) and styles inserted by Angular with the `nonce-randomNonceGoesHere`. |
191-
| `script-src 'self' 'nonce-randomNonceGoesHere';` | Allows the page to load JavaScript from the same origin \(`'self'`\) and scripts inserted by the Angular CLI with the `nonce-randomNonceGoesHere`. This is only required if you're using critical CSS inlining. |
186+
| Sections | Details |
187+
| :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
188+
| `default-src 'self';` | Allows the page to load all its required resources from the same origin. |
189+
| `style-src 'self' 'nonce-randomNonceGoesHere';` | Allows the page to load global styles from the same origin \(`'self'`\) and styles inserted by Angular with the `nonce-randomNonceGoesHere`. |
190+
| `script-src 'self' 'nonce-randomNonceGoesHere';` | Allows the page to load JavaScript from the same origin \(`'self'`\) and scripts inserted by the Angular CLI with the `nonce-randomNonceGoesHere`. Required only when you enable critical CSS inlining or subresource integrity, which add inline scripts to `index.html`. |
192191

193192
Angular itself requires only these settings to function correctly.
194193
As your project grows, you may need to expand your CSP settings to accommodate extra features specific to your application.
195194

195+
#### Static hosting without per-response nonces
196+
197+
If your hosting environment or CDN can replace a placeholder token in cached HTML at the edge (for example, using SSI, ESI, or an edge function), you can build `index.html` with a placeholder in `ngCspNonce` (such as `<app ngCspNonce="__CSP_NONCE__"></app>`) and replace it with a unique nonce on each response.
198+
199+
If you deploy your application to a static host that serves `index.html` unchanged without edge transformation, do not hard-code a static nonce. Instead, use one of the following approaches:
200+
201+
##### Hash inline scripts with `autoCsp`
202+
203+
Set the `security.autoCsp` option to `true` in the [workspace configuration](reference/configs/workspace-config#extra-build-and-test-options).
204+
At build time, the Angular CLI computes a hash of every inline script in `index.html`, including the scripts added by critical CSS inlining and subresource integrity.
205+
The CLI replaces the `<script src>` elements with a hashed loader script and adds a `<meta>` tag at the start of `<head>`:
206+
207+
```txt
208+
script-src 'strict-dynamic' 'sha256-...' https: 'unsafe-inline'; object-src 'none'; base-uri 'self';
209+
```
210+
211+
Because hashes depend only on the content of the scripts, `index.html` remains valid for every visitor and can be cached.
212+
Browsers that support hashes and `'strict-dynamic'` ignore the `https:` and `'unsafe-inline'` fallback sources.
213+
214+
The policy generated by `autoCsp` has the following limitations:
215+
216+
- It only covers scripts. You must configure `style-src` separately.
217+
- Browsers ignore some directives, such as `frame-ancestors`, `report-uri`, and `sandbox`, when they appear in a `<meta>` tag. Send these directives in a `Content-Security-Policy` HTTP header.
218+
- When a page has multiple policies, the browser enforces all of them. If you also send a CSP header, omit both `script-src` and `default-src` from the header so they do not block the hashed inline scripts.
219+
- You cannot use `autoCsp` with server-side rendering.
220+
221+
##### Avoid inline scripts
222+
223+
The Angular CLI only adds inline scripts to `index.html` for critical CSS inlining and subresource integrity.
224+
If you set `optimization.styles.inlineCritical` to `false` and leave `subresourceIntegrity` disabled, `index.html` does not contain inline scripts. You can then configure a `Content-Security-Policy` header with `script-src 'self'`.
225+
226+
NOTE: Disabling critical CSS inlining can slow down the initial render of your application, and disabling subresource integrity removes script integrity checks.
227+
228+
##### Configure styles for static hosting
229+
230+
Angular inserts `<style>` elements for component styles at runtime, and critical CSS inlining adds a `<style>` element to `index.html`.
231+
Neither `autoCsp` nor disabling inline scripts covers these styles. Without a per-response nonce, allow them by adding `'unsafe-inline'` to `style-src`.
232+
For example, if your build avoids inline scripts, configure your host to send the following header:
233+
234+
```txt
235+
default-src 'self'; style-src 'self' 'unsafe-inline';
236+
```
237+
238+
If you use `autoCsp`, send `style-src 'self' 'unsafe-inline'` in the HTTP header without `default-src` or `script-src`.
239+
240+
Your application code and third-party libraries might require additional directives in both cases.
241+
196242
### Enforcing Trusted Types
197243

198244
It is recommended that you use [Trusted Types](https://w3c.github.io/trusted-types/dist/spec/) as a way to help secure your applications from cross-site scripting attacks.

0 commit comments

Comments
 (0)