Conceptual diagram of strict-dynamic trust flowing from a nonce-authorized script to dynamically added scripts

strict-dynamic lets a script authorized by a nonce or hash extend trust to scripts it adds dynamically. In supporting browsers, this can reduce dependence on an expanding host allowlist by centering policy on an approved bootstrap script and its loader. Read the execution rules in CSP Level 3 alongside web.dev’s strict CSP guide to understand the scope.

A nonce-authorized bootstrap and its loader

The server generates an unpredictable nonce for each response and puts the same value in the CSP header and the <script> elements it intends to run. A browser that supports strict-dynamic can trust nonce- or hash-authorized scripts and non-parser-inserted scripts they add dynamically. In that browser, host and scheme sources may act as compatibility fallbacks rather than the primary trust decision.

Content-Security-Policy: script-src 'nonce-{per-response-random}' 'strict-dynamic'; object-src 'none'; base-uri 'none'

This does not mean that one keyword blocks every threat. If a trusted loader turns unchecked user input into script.src, it may load code the policy author did not intend. Treat URLs, manifests, and configuration read by the loader as part of the code-execution boundary.

`'unsafe-eval'` is a separate permission

strict-dynamic and 'unsafe-eval' control different behavior. When 'unsafe-eval' is allowed by script-src or its fallback, APIs such as eval(), the Function() constructor, and string arguments to setTimeout() or setInterval() can evaluate JavaScript dynamically again. Adding strict-dynamic does not cancel that permission. Find whether a runtime or build artifact relies on string evaluation, then remove it or assess its need separately.

A nonce- or hash-based policy restricts ordinary inline scripts in supporting browsers, but CSP does not repair an HTML injection flaw. Generate a fresh nonce per response; do not treat it as a secret hidden from code that is already authorized to run in the same page. Fix injection at its source with safe DOM APIs and contextual output encoding, and validate inputs to trusted loaders.

Roll out with Report-Only first

Enforcing a policy immediately can break inline event handlers or scripts the application inserts dynamically. Start with Content-Security-Policy-Report-Only, review violations, move needed behavior into event listeners, and verify normal flows and script-loading paths. Then enforce in stages while continuing to inspect reports. A quiet report is not proof that the application has no XSS flaw.

Older browsers that do not understand strict-dynamic can apply a different fallback policy. web.dev describes considering sources such as https: for some older browsers, but a fallback can broaden what those browsers trust. Test the actual application and browser versions together before deciding which compatibility sources to retain.

Before enforcement

  • Does the server generate a sufficiently unpredictable nonce for each response?
  • Is the nonce attached only to intended script elements and matched in the header?
  • Can a trusted loader turn attacker-controlled data into a script URL?
  • Have you located and separately reviewed 'unsafe-eval'?
  • Have you checked Report-Only reports and fallback behavior in real browsers?

CSP is one layer that restricts script execution in the browser. It does not replace authentication, authorization, safe output handling, fixing vulnerable code, or the application’s other security controls.

Sources