strict-dynamic in script-src
Why it matters
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.
Severity rationale
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.
Remediation
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.
Detection
-
ID:
strict-dynamic -
Severity:
high -
What to look for: Parse all CSP directives. Check whether
script-srcincludes'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-srcincludes'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-srcdoes 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.
External references
- cwe · CWE-79
- cwe · CWE-693
- owasp:2021 · A03
Taxons
History
- 2026-04-18·v1.0.0·Initial import from security-headers-ii·automated