script-src-elem
The CSP script-src-elem directive controls which sources script elements can load. See its fallback chain, values, examples, and risks.
Last update:
The script-src-elem directive in a Content Security Policy (CSP) controls which scripts can load through a <script> element, whether the element points to an external file or holds an inline script block. It does not cover inline event handler attributes like onclick, those belong to script-src-attr. Use script-src-elem when you want a different rule for <script> tags than for handlers.
A minimal safe policy for this directive, nonce-based rather than a host allowlist:
Content-Security-Policy: script-src-elem 'nonce-{RANDOM}' 'strict-dynamic'Fallback chain
script-src-elem falls back to script-src, then to default-src. If you do not set script-src-elem, <script> elements are checked against script-src, and if that is also absent, against default-src. Setting script-src-elem fully replaces script-src for <script> elements.
Because the broader script-src already covers script elements, most policies never need script-src-elem. Reach for it only when you want script elements and inline handlers to follow separate rules.
Values
script-src-elem takes the same value kinds as script-src, or 'none'.
| Value | Status | Description |
|---|---|---|
'none' | ✅ Good | Blocks every <script> element. Used alone. |
'self' | ✅ Good | Script elements from your own origin only. |
| Host source | ✅ Good | A specific host such as https://cdn.example.com. |
https: | ✅ Good | Any origin over TLS. Very broad for scripts. |
data: | ❌ Risky | Attacker-controlled data: URLs execute as script. |
blob: | ❌ Risky | blob: URLs execute as script, an XSS vector. |
'nonce-...' | ✅ Good | Matches a <script> element carrying the same nonce attribute. |
'sha256-...' | ✅ Good | Digest of an exact inline block or external file. |
'strict-dynamic' | ✅ Good | Trust flows from nonce or hash allowed elements; host and scheme sources are ignored. |
'report-sample' | ✅ Good | Adds the first 40 characters of blocked inline code to reports. |
'unsafe-inline' | ❌ Risky | Allows every inline <script> block, including injected ones. |
It accepts:
- Keyword sources such as
'self','unsafe-inline', and'strict-dynamic'. - A nonce or hash to allow specific inline or external script elements.
- A host source such as
https://cdn.example.com. - A scheme source such as
https:.
Nonces and hashes apply here just as they do on script-src. A nonce on a <script> element matches only when the element carries the same nonce attribute, and a hash matches the exact text content of an inline block.
Examples
Allow same-origin script elements and a CDN, while a nonce admits one inline block:
Content-Security-Policy: script-src-elem 'self' https://cdn.example.com 'nonce-r4nd0m'Common use
A typical use is to allow your own scripts and a small set of trusted hosts for <script> elements, then control handlers separately with script-src-attr; how the two directives split script-src walks through the whole split with a worked example. As with script-src, the strong pattern is a nonce or hash plus 'strict-dynamic' rather than a host allowlist, see the strict-dynamic guide and the nonce setup guide.
Security notes
script-src-elem blocks injected <script> tags that do not match the source list. Adding a nonce or hash makes 'unsafe-inline' ignored, which is what stops an attacker from injecting an inline <script> block.
'unsafe-inline'allows any inline<script>, including injected ones. Replace it with a nonce or hash, see why to drop unsafe-inline.- Compute hashes for static inline blocks with the hash generator, and check the resulting policy with the CSP evaluator.
Known bypasses and risks
The host allowlist weakness applies here too: an open redirect or JSONP endpoint on an allowed origin can load arbitrary script through a <script> element. 'strict-dynamic' removes the allowlist from the decision and trusts only nonce or hash allowed elements and the scripts they create.
A subtle risk is forgetting that script-src-elem does not cover handlers. If you tighten script-src-elem but leave script-src (or default-src) permissive, inline onclick= handlers may still run, because they resolve through script-src-attr.
Recommendation
Set the strict, nonce-based policy on script-src and let <script> elements inherit it through the fallback:
Content-Security-Policy:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
object-src 'none';
base-uri 'none'This is the strict CSP that the OWASP CSP cheat sheet and web.dev recommend, and it covers script elements without a separate script-src-elem. Set script-src-elem only when elements and inline handlers genuinely need different rules, and keep it nonce or hash based rather than a host allowlist.
Reporting
A blocked <script> element produces a csp-violation report with script-src-elem as the effective directive. Add 'report-sample' to include a short sample of the blocked content. CentralCSP collects these reports and uses CSP hash reporting to build a script inventory of every script element on your pages.
Browser support
Widely supported across current browsers.