You are deploying a strict nonce-based CSP for an Angular banking dashboard; what does Angular itself require in the policy, and which app features would force you to loosen it?
answer
- the guide's minimal policy
- styles need the nonce
- script nonce for inlined critical CSS
- JIT, JSONP, bypasses
- fix the feature, not the policy
basics
~20 sAngular's minimal policy is default-src 'self' plus a per-response nonce in style-src and script-src, handed to Angular via ngCspNonce or CSP_NONCE. JIT compilation, JSONP, bypassed values under Trusted Types and missing nonce plumbing are what push teams to loosen it.
solid answer
~40 sStart from the guide's minimal policy: `default-src 'self'; style-src 'self' 'nonce-…'; script-src 'self' 'nonce-…'`. The style nonce exists because Angular inserts component styles as `<style>` elements at runtime, so it must receive the per-response value through `ngCspNonce` or `CSP_NONCE`. The script nonce is only needed when the build inlines critical CSS, and then the nonce must come from `ngCspNonce` or `autoCsp`, not the token. An AOT build needs no `'unsafe-eval'`. What forces loosening is usually a feature. A JIT bootstrap needs `'unsafe-eval'`. If you cannot generate nonces, you are left with `'unsafe-inline'` for styles. JSONP calls need the external host in `script-src`. Under Trusted Types, bypass calls need `angular#unsafe-bypass`. For a banking dashboard the right move is to remove each feature rather than widen the policy.
go deeper
Recall the guide's minimal policy: default-src 'self', and a nonce in style-src and script-src.
Explain why each directive is there, especially that style-src needs the nonce because Angular inserts component styles at runtime.
Audit the app for features that force loosening, such as JIT, JSONP, bypasses and missing nonce plumbing, and replace them instead of widening the header.
Own the risk posture: which relaxations are acceptable for a money-moving app, who signs off, and how the policy stays strict as features are added.
## The target: what Angular needs and nothing more A strict CSP for a high-value app such as a banking dashboard aims to let only the app's own code run. Angular's security guide gives the **minimal policy** a new Angular app needs: ```txt default-src 'self'; style-src 'self' 'nonce-randomNonceGoesHere'; script-src 'self' 'nonce-randomNonceGoesHere'; ``` Reading it directive by directive: | Directive | Why Angular needs it | | :--- | :--- | | `default-src 'self'` | the bundle, assets and API calls come from the app's own origin | | `style-src 'self' 'nonce-…'` | global stylesheets from the origin, plus the `<style>` elements Angular inserts for component styles | | `script-src 'self' 'nonce-…'` | bundled scripts from the origin; the nonce is only required when critical CSS is inlined | Notice what is absent: no `'unsafe-inline'` and no `'unsafe-eval'`. An AOT build never evaluates strings as code, so it does not need the latter. ## Step 1: give Angular the nonce The nonce must be random and **unique per response**; the guide stresses it must not be predictable. Angular then needs the value so it can stamp it on the styles it inserts: 1. **`ngCspNonce` on the root element** when the server renders `index.html` per response. 2. **`CSP_NONCE` injection token** when the value is available at runtime and `index.html` should be cacheable. 3. **`autoCsp`** in the workspace configuration, the CLI-driven route. If the build **inlines critical CSS**, the guide says to use the attribute or `autoCsp`, because the token cannot reach styles written into the HTML file. With server-side rendering and hydration's event replay, the same token also supplies the nonce for the inline replay script Angular adds to the page. ## Step 2: find the features that fight the policy Each of these is a common reason teams end up weakening the header: - **JIT compilation** (`platformBrowserDynamic`, the runtime compiler) needs `'unsafe-eval'`. Fix: build with AOT; the JIT bootstrap package is deprecated since Angular 20. - **No nonce plumbing**: without a nonce, component styles are blocked and the only fallback the guide offers is `'unsafe-inline'` in `style-src`. Fix: pick one of the three channels above. - **JSONP** through `HttpClient` injects a `<script>` from another origin. Angular stamps the nonce on it, but the host is still external code executing in your page. Fix: use CORS-enabled JSON endpoints instead; `withJsonpSupport()` is deprecated since Angular 22.1 for exactly this XSS risk. - **Bypassed values** under Trusted Types need `angular#unsafe-bypass`. Fix: sanitize instead of bypassing wherever possible. - **Lazy routes** under Trusted Types need `angular#bundler`. This one is expected and safe to allow. ## Step 3: verify before enforcing Use the same header in development and tests as in production, so a missing nonce shows up as unstyled components in `ng serve` rather than in front of customers. Typical first-run symptoms and their Angular causes: - components render without styling: the nonce is not reaching Angular; - a blank page with an eval violation: something is still compiled JIT; - only certain widgets fail under Trusted Types: they rely on a bypass or write to the DOM directly. How the nonce travels from the edge to the HTML, `strict-dynamic`, and report-only rollouts are general CSP deployment topics; the Angular-specific part is the list above. ## A rollout checklist for the dashboard 1. Build with AOT and confirm the bootstrap uses `bootstrapApplication`. 2. Choose the nonce channel from how `index.html` is served, and handle critical-CSS inlining if the build uses it. 3. Remove JSONP calls and review every `bypassSecurityTrust*` call. 4. Apply the header in development, tests and staging before production. 5. Add Trusted Types enforcement with `angular` and `angular#bundler` once the CSP itself is clean. ## The judgment call For a dashboard that moves money, every loosening token is a standing risk, so the default answer is to **change the feature, not the policy**. The one relaxation Angular's guide itself offers, `'unsafe-inline'` for styles when nonces are impossible, is weaker but far less dangerous than anything in `script-src`. `'unsafe-eval'` or a broad script host list should be treated as a blocker, not a trade-off.
- Does an AOT-built Angular app ever need 'unsafe-eval' in script-src?Not for Angular itself: templates are compiled at build time and nothing is evaluated from strings at runtime. If a violation mentions eval, look for a JIT bootstrap, the runtime compiler or a third-party library that evaluates strings.
- The dashboard uses server-side rendering; what else needs the nonce?When hydration's event replay is in use, Angular's server rendering adds a small inline script that starts replaying events captured before the app booted, and it puts the `CSP_NONCE` value on that script. So the per-request nonce must be provided to the server-side application as well, not only in the browser.
saying these in an interview costs you the question
- Angular's minimal CSP needs 'unsafe-eval' for template bindings.
- Angular generates and injects the nonce itself, so the server does nothing.
- One nonce value can be reused across responses if it is long enough.
- 'unsafe-inline' in script-src is the guide's recommended fallback.
- JSONP is fine under a strict CSP because Angular adds the nonce.