Without 'strict-dynamic', every module your bundler or runtime loads dynamically must be individually allowlisted in CSP. In practice this means developers add 'unsafe-inline' or broad domain wildcards as a shortcut, silently destroying XSS protection. 'strict-dynamic' delegates trust from an allowlisted script (identified by nonce or hash) to every script it loads — removing the need for individual allowlisting of dynamic imports. CWE-79 and CWE-693 both apply: the absence forces teams toward CSP configurations that the OWASP A03 guidance explicitly flags as ineffective for modern SPAs and module-heavy codebases.
High because omitting `'strict-dynamic'` forces a choice between a broken CSP that blocks legitimate dynamic imports and a weakened one that uses unsafe fallbacks, both of which undermine XSS protection.
Add 'strict-dynamic' alongside your nonce in script-src. This single keyword makes dynamically loaded modules inherit trust from the bootstrapping script without requiring per-module allowlisting.
Content-Security-Policy: script-src 'nonce-{perRequestValue}' 'strict-dynamic'; object-src 'none'; base-uri 'self'
When 'strict-dynamic' is present, browsers automatically ignore domain allowlists and 'unsafe-inline' in supporting browsers — you can include them as fallbacks for older browsers without weakening policy. Do not pair 'strict-dynamic' with 'unsafe-inline' unless a nonce is also present; the nonce causes conforming browsers to ignore 'unsafe-inline' automatically.
ID: security-headers-ii.csp-quality.strict-dynamic
Severity: high
What to look for: Parse all CSP directives. Check whether script-src includes 'strict-dynamic'. 'strict-dynamic' allows scripts loaded by already-trusted scripts to execute without individual allowlisting — it simplifies CSP management for apps with many dynamically loaded modules. Count the total number of CSP directives.
Pass criteria: script-src includes 'strict-dynamic'. Count the total number of CSP directives (at least 3 expected in a well-configured policy) and report: "CSP has X directives total; script-src includes strict-dynamic."
Fail criteria: script-src does not include 'strict-dynamic'.
Do NOT pass when: 'strict-dynamic' is present but 'unsafe-inline' is also present WITHOUT a nonce — they conflict. When both 'strict-dynamic' and a nonce are present, 'unsafe-inline' is automatically ignored by conforming browsers, which is the correct pattern. Fail with detail explaining the conflict if 'unsafe-inline' appears without a nonce alongside 'strict-dynamic'.
Skip (N/A) when: No Content-Security-Policy header configured. Run Security Headers & Basics first.
Detail on fail: "script-src does not include 'strict-dynamic' — dynamically loaded scripts require individual allowlisting" or "strict-dynamic and unsafe-inline both present without a nonce — they conflict"
Remediation: 'strict-dynamic' tells the browser: "trust scripts loaded by already-trusted scripts." This is essential for apps that load modules dynamically:
script-src 'nonce-abc123' 'strict-dynamic'
When 'strict-dynamic' is present, domain allowlists and 'unsafe-inline' are automatically ignored in supporting browsers, so you can include them as fallbacks for older browsers without weakening the policy.