Keywords
Reference for CSP keyword sources, self, none, unsafe-inline, unsafe-eval, strict-dynamic, unsafe-hashes, report-sample, and what each one allows.
Last update:
Keyword sources are the single-quoted tokens you put in a Content Security
Policy (CSP) source list, such as 'self', 'none', 'unsafe-inline', and
'strict-dynamic'. Each one switches on a specific behavior rather than naming a
URL, so they decide how the browser treats inline code, dynamic script, and your
own origin. The quotes are part of the token; drop them and the browser reads the
word as a hostname.
A safe use, keywords carrying a strict script policy:
Content-Security-Policy: script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic'Syntax
A keyword source is a fixed token wrapped in single quotes, listed alongside any host, scheme, nonce, or hash sources in a directive value.
Content-Security-Policy:
script-src 'self' 'strict-dynamic' 'nonce-r4nd0m';
object-src 'none';
base-uri 'none'Keyword names are case-insensitive, but the quotes are required. Most keywords are
only meaningful in the directives that fetch script or style; 'self' and
'none' work in any source-list directive.
What each keyword does
| Keyword | Status | What it allows |
|---|---|---|
'self' | ✅ Good | The page's own origin, the exact scheme, host, and port. Does not include subdomains, and does not allow inline code. |
'none' | ✅ Good | Nothing. Used alone to block every source for a directive. |
'strict-dynamic' | ✅ Good | Trust to propagate from a nonce or hash allowed script to the scripts it loads. Turns off host and scheme allowlists. |
'wasm-unsafe-eval' | ✅ Good | WebAssembly compilation and instantiation only, not JavaScript eval(). Widely supported across current browsers. |
'report-sample' | ✅ Good | A short sample (the first 40 characters) of the blocked content to appear in the violation report. Reporting aid only. |
'trusted-types-eval' | ✅ Good | eval() only when it receives a TrustedScript and Trusted Types are enforced. New; recently became available across current Chrome, Firefox, and Safari. |
'unsafe-inline' | ❌ Risky | Inline <script> and <style> blocks, javascript: URLs, and inline event handlers. Defeats the main XSS protection. |
'unsafe-eval' | ❌ Risky | eval(), new Function(), and setTimeout/setInterval called with a string. See unsafe-eval. |
'unsafe-hashes' | ❌ Risky | Hash sources to match inline event handlers and style= attributes. Cross-browser, but re-enables the event-handler surfaces. |
'inline-speculation-rules' | 🧪 Experimental | Inline <script type="speculationrules"> blocks. Chromium-led; not in the CSP grammar. |
'report-sha256' / 'report-sha384' / 'report-sha512' | 🧪 Experimental | Report-only script hash collection via csp-hash reports. Chromium-only. |
'unsafe-webtransport-hashes' | 🧪 Experimental | WebTransport connections matched by certificate hash. In the spec grammar; no documented browser support. |
'unsafe-allow-redirects' | ⚠️ Deprecated | Nothing in practice. A vestigial leftover of the removed navigate-to directive, with no functional definition and no browser support. |
Two rules that change how keywords interact
Two interactions catch people out, because adding one keyword silently disables another.
A nonce or a hash makes 'unsafe-inline' ignored. When a script-src or
style-src value contains a nonce source or a hash source, the browser drops
'unsafe-inline' from that directive. So once you add a nonce or a hash, remove
'unsafe-inline': it has no effect, and leaving it in only makes the policy
harder to read. Do not rely on 'unsafe-inline' being active when a nonce is
present.
Content-Security-Policy: script-src 'unsafe-inline' 'nonce-r4nd0m'In that policy, only scripts carrying nonce="r4nd0m" run; 'unsafe-inline' has
no effect.
'strict-dynamic' ignores host and scheme allowlists. When 'strict-dynamic' is
present in script-src, the browser ignores every host-source and scheme-source
entry (and 'unsafe-inline') in that directive. Only nonce or hash allowed
scripts run, plus any scripts they create at runtime. This is what lets a strict
policy avoid maintaining a host allowlist. See
strict-dynamic for the full pattern.
Content-Security-Policy:
script-src 'strict-dynamic' 'nonce-r4nd0m' https://cdn.example.comHere https://cdn.example.com is ignored. The CDN script only loads if the
nonce-allowed bootstrap script injects it.
The newer keywords
'trusted-types-eval' is the newest addition to the keyword set. It allows
eval() and its relatives only when the argument is a TrustedScript, and only
while Trusted Types are enforced with
require-trusted-types-for.
Use it instead of 'unsafe-eval' when a dependency genuinely needs eval: the
string still has to pass a Trusted Types policy you wrote, so injected text
cannot reach the interpreter. It recently became available across current Chrome,
Firefox, and Safari, so treat it as safe but very new.
The report-only hash keywords
'report-sha256', 'report-sha384', and 'report-sha512'
never allow or block anything; they ask the browser to report a hash of each
script it runs. They are in the CSP3 editor's draft grammar and stable in
Chromium, with no Firefox or Safari support yet.
'inline-speculation-rules' allows inline
<script type="speculationrules"> blocks and nothing else. It is a Chromium-led
extension that is not part of the CSP grammar (Safari has it behind a flag), so
count on it only for Chromium users. 'unsafe-webtransport-hashes' sits in the
spec grammar with no documented browser support, and 'unsafe-allow-redirects'
is a leftover of the removed
navigate-to
directive with no functional definition; neither belongs in a real policy.
Insecure values to avoid
'unsafe-inline' and 'unsafe-eval' are the two values that turn off the
protection CSP exists to provide. An attacker who injects markup into your page
can run inline script the moment 'unsafe-inline' is in script-src, which is
the exact attack a policy is meant to block. Replace 'unsafe-inline' with a
nonce or a hash,
and replace 'unsafe-eval' by removing the eval-style calls or by moving them
behind Trusted Types with 'trusted-types-eval'. Treat 'unsafe-hashes' as a
last resort for legacy inline handlers: it is standard and cross-browser, but it
re-opens the event-handler attack surface a policy is meant to close, so scope
it to the specific hashes you need.
What it protects against
Keywords are how a policy expresses the difference between trusting an origin and
trusting arbitrary inline code. Using 'self' with a nonce and 'strict-dynamic'
instead of 'unsafe-inline' blocks injected <script> blocks and inline handlers,
which is the core defense against cross-site scripting (XSS). You can audit how a
policy uses these keywords with the CSP evaluator.
Known limitations
The nonce-suppresses-'unsafe-inline' and 'strict-dynamic'-ignores-allowlists
rules apply to script-src (and, for 'unsafe-inline', style-src); they do not
change behavior in directives that never accepted inline code. 'report-sample'
only adds a sample to reports and never affects whether content is blocked.
'inline-speculation-rules' and the 'report-sha...' keywords are effectively
Chromium-only, so do not rely on them for behavior in Firefox or Safari. The
webrtc directive
takes its own pair of keywords, 'allow' and 'block', which are valid nowhere
else.
Risks
Leaving 'unsafe-inline' or 'unsafe-eval' in a production script-src is the
most common way a CSP ends up providing little protection. The reverse risk is
adding a nonce or 'strict-dynamic' and forgetting that it disables the host
allowlist you were relying on, which can break legitimate scripts until you tag
them with the nonce or let 'strict-dynamic' propagate trust to them.
Examples
A strict policy that trusts inline script by nonce and lets that script load the rest:
Content-Security-Policy:
script-src 'nonce-r4nd0m' 'strict-dynamic';
object-src 'none';
base-uri 'none'A style policy that allows two specific inline styles by hash and blocks the rest:
Content-Security-Policy: style-src 'self' 'sha256-abc123...' 'sha256-def456...'Recommendation
Build script trust on a
nonce or hash
plus 'strict-dynamic', and keep the unsafe-* keywords out of the policy. Set
the remaining directives explicitly so nothing falls back implicitly:
Content-Security-Policy:
default-src 'self';
script-src 'nonce-{RANDOM}' 'strict-dynamic';
style-src 'self';
img-src 'self';
font-src 'self';
connect-src 'self';
media-src 'self';
manifest-src 'self';
frame-src 'none';
worker-src 'self';
object-src 'none';
base-uri 'none';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
report-to csp-endpointReporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"This is the strict CSP pattern the
OWASP CSP cheat sheet
and the web.dev strict CSP guide
recommend: individual scripts are trusted by nonce or hash, 'strict-dynamic'
lets them load what they need, and no 'unsafe-inline' or 'unsafe-eval'
re-opens the injection paths the policy exists to close.
Browser support
'self', 'none', 'unsafe-inline', 'unsafe-eval', 'strict-dynamic',
'unsafe-hashes', 'report-sample', and 'wasm-unsafe-eval' are supported
across current browsers. 'trusted-types-eval' is cross-browser but very
recent, having just become available across current Chrome, Firefox, and Safari.
'inline-speculation-rules' and
the 'report-sha...' keywords run in Chromium only, and
'unsafe-webtransport-hashes' and 'unsafe-allow-redirects' have no browser
support at all.
FAQ
What does strict-dynamic do?
'strict-dynamic' lets trust propagate from a nonce or hash allowed script to the scripts it creates at runtime. When it is present in script-src, the browser ignores every host-source and scheme-source entry (and 'unsafe-inline') in that directive, so a strict policy avoids maintaining a host allowlist.
Is unsafe-inline safe if I also use a nonce?
When a script-src or style-src value contains a nonce or hash source, the browser ignores 'unsafe-inline' in that directive, so it is harmless but pointless: only nonce-matched scripts run. Leaving it in adds nothing except clutter, so remove it once you add a nonce or hash.
See also
- script-src directive
- style-src directive
- Host source
- Hashes and nonces
- report-sha256 keyword
- How to remove unsafe-inline
- Replacing unsafe-eval
- Building a strict policy with strict-dynamic