CentralCSP
PoliciesContent-Security-PolicyDirectives

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'.

ValueStatusDescription
'none'✅ GoodBlocks every <script> element. Used alone.
'self'✅ GoodScript elements from your own origin only.
Host source✅ GoodA specific host such as https://cdn.example.com.
https:✅ GoodAny origin over TLS. Very broad for scripts.
data:❌ RiskyAttacker-controlled data: URLs execute as script.
blob:❌ Riskyblob: URLs execute as script, an XSS vector.
'nonce-...'✅ GoodMatches a <script> element carrying the same nonce attribute.
'sha256-...'✅ GoodDigest of an exact inline block or external file.
'strict-dynamic'✅ GoodTrust flows from nonce or hash allowed elements; host and scheme sources are ignored.
'report-sample'✅ GoodAdds the first 40 characters of blocked inline code to reports.
'unsafe-inline'❌ RiskyAllows every inline <script> block, including injected ones.

It accepts:

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.

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.

See also

Sources

On this page