Skip to content
script-src.com
script-src.com
EN / FR

strict-dynamic

How the strict-dynamic keyword propagates trust from a nonce or hash to dynamically loaded scripts, and the recommended strict CSP pattern.

'strict-dynamic' lets a script you have already trusted, through a nonce or a hash, load further scripts without each one needing its own allowlist entry. It is the practical way to run a strict CSP on a site with many third-party scripts.

The problem it solves

Host allowlists are hard to keep both safe and complete. A single trusted CDN that also hosts an exploitable endpoint, or a tag manager that loads dozens of changing vendors, makes an accurate host list nearly impossible. script-src host lists are also a common source of bypasses.

'strict-dynamic' replaces the host list with a chain of trust. You trust one top-level script with a nonce or hash, and any script it creates with the DOM is trusted too.

How trust propagates

When 'strict-dynamic' is present, a script that was allowed by a nonce or hash can create more scripts, for example with document.createElement('script'), and those inherit the trust:

Content-Security-Policy: script-src 'nonce-r4nd0m' 'strict-dynamic'
<script nonce="r4nd0m" src="https://loader.example.com/tag.js"></script>

Here tag.js is trusted by its nonce. Any script tag.js injects through the DOM is also allowed, with no host entry required.

Trust does not propagate to markup-based script injection such as document.write or setting innerHTML. Those remain blocked, which is the point: legitimate loaders use the DOM API, most XSS uses markup.

Host and self sources are ignored

When a browser honors 'strict-dynamic', it ignores host sources, scheme sources, and 'self' in the same directive. Trust comes only from the nonce or hash and the chain it starts. This is deliberate, and it means you cannot mix a strict-dynamic policy with a host allowlist for the same directive.

A widely used baseline that stays safe on modern browsers and degrades on old ones:

Content-Security-Policy:
  script-src 'nonce-r4nd0m' 'strict-dynamic' 'unsafe-inline' https:;
  object-src 'none';
  base-uri 'none'

How each part is read:

  • Modern browsers use the nonce and 'strict-dynamic', and ignore 'unsafe-inline' and https:.
  • Browsers that support nonces but not 'strict-dynamic' fall back to the nonce plus https:.
  • Very old browsers with no nonce support fall back to 'unsafe-inline'.

object-src 'none' and base-uri 'none' close two bypasses that a script-src-only policy leaves open.

When not to use it

If your site has a small, stable set of script hosts and no dynamic loaders, a plain host allowlist or 'self' plus nonces is simpler to reason about. Reach for 'strict-dynamic' when the host list is the thing that has become unmanageable.