default-src
The CSP default-src directive sets the fallback source list for most fetch directives, so anything you do not name explicitly inherits it.
Last update:
The default-src directive is the fallback source list for most fetch directives in a Content Security Policy (CSP). Any fetch directive you do not set explicitly inherits the sources you give default-src, so it is the safety net that decides what loads when a more specific rule is absent.
A minimal safe policy for this directive:
Content-Security-Policy: default-src 'self'Fallback chain
default-src itself has no fallback. It is the bottom of the chain: when the browser checks a resource, it looks for the most specific directive first, and only falls back to default-src if that directive is not present in the policy.
Setting default-src 'self' does not mean every directive is now 'self'. It means every fetch directive you omit behaves as 'self'. The moment you add a specific directive, for example script-src, that directive takes over for scripts and default-src no longer applies to them. A common mistake is setting script-src and assuming images are still covered: they are, but only through default-src, so you have to keep default-src in place or name img-src too.
The directives default-src backs include script-src, style-src, img-src, font-src, connect-src, media-src, object-src, manifest-src, and worker-src (through child-src).
A fetch resolves to its own directive when that directive is present, and falls back to default-src only when it is absent:
The document and navigation directives do not take part in this chain. base-uri, form-action, frame-ancestors, sandbox, and the reporting directives never fall back to default-src, so an unset one of these stays unset.
What default-src does not cover
This is the most common CSP misunderstanding. default-src is only a fallback for the fetch directives. It does not cover the document and navigation directives:
base-uriform-actionframe-ancestorssandbox- The reporting directives
report-uriandreport-to
If you want to restrict where forms post or which sites may frame your page, you have to set those directives yourself. default-src 'self' does nothing for them. Leaving base-uri unset, for example, is a real cross-site scripting vector even with a tight default-src.
Values
default-src takes a space-separated source list, the same grammar every fetch directive uses. Because it is the fallback for the fetch directives, it accepts everything script-src does; the script-only keywords take effect when the fallback ends up governing a script check.
| Value | Status | Description |
|---|---|---|
'none' | ✅ Good | Blocks every fetch the policy governs. Used alone. |
'self' | ✅ Good | Resources from your own origin only. |
| Host source | ✅ Good | A specific host such as cdn.example.com. |
https: | ❌ Risky | Any origin over TLS, including for scripts through the fallback. |
data: | ❌ Risky | Executes as script through the fallback. Allow it on img-src or font-src instead. |
blob: | ❌ Risky | blob: URLs execute as script through the fallback. |
'nonce-...' | ✅ Good | Per-response random token; only meaningful for scripts and styles. |
'sha256-...' | ✅ Good | Digest of an exact inline block; only meaningful for scripts and styles. |
'strict-dynamic' | ✅ Good | Applies when the fallback governs scripts; host and scheme sources are then ignored. |
'wasm-unsafe-eval' | ✅ Good | WebAssembly compilation only, narrower than 'unsafe-eval'. |
'report-sample' | ✅ Good | Adds the first 40 characters of blocked inline content to reports. |
'trusted-types-eval' | ✅ Good | Allows eval only with TrustedScript when Trusted Types are enforced. Recently became available across current Chrome, Firefox, and Safari. |
'unsafe-inline' | ❌ Risky | Allows every inline script and style, including injected ones. |
'unsafe-eval' | ❌ Risky | Allows eval(), new Function(), and string timers. |
'unsafe-hashes' | ❌ Risky | Lets hashes match inline event handlers, re-enabling that surface. |
'inline-speculation-rules' | 🧪 Experimental | Inline speculation rules scripts. Chromium-led, not on the standards track. |
'report-sha256' / 'report-sha384' / 'report-sha512' | 🧪 Experimental | Report-only hash collection. Chromium-only. |
You can combine:
- the keyword sources such as
'self'and'none' - a host source such as
cdn.example.comor*.example.com - a scheme source such as
https: - a nonce or hash source, though these only make sense for scripts and styles
default-src 'none' blocks every fetch the policy governs, which is a strict baseline you then open up directive by directive.
Examples
Content-Security-Policy:
default-src 'self';
img-src 'self' data:;
object-src 'none'Here scripts, styles, fonts, media, and connections all fall back to 'self'. Images additionally allow data: URIs, and plugins are blocked outright. Anything not named inherits 'self' from default-src.
Security notes
default-src 'self' is a reasonable floor, but on its own it still allows same-origin inline scripts to be loaded as external files and does nothing for the document directives above. For a strong policy, set default-src as the catch-all, then tighten the high-risk directives explicitly: a nonce or hash plus 'strict-dynamic' on script-src, object-src 'none', and base-uri 'none'. You can check a draft policy for gaps with the CSP evaluator before you ship it.
Avoid default-src * or a wildcard scheme like default-src https:, which allows loading from any host and gives almost no protection. A bare * does not match data:, blob:, or filesystem:, so a wildcard is both too broad and quietly incomplete.
Known bypasses and risks
The real risk with default-src is over-trusting it. Because it does not cover base-uri, form-action, frame-ancestors, or sandbox, a policy of default-src 'self' alone leaves clickjacking, base-tag injection, and form-action exfiltration open. Set those directives directly.
If you rely on default-src to cover scripts but the page needs an inline script, you cannot loosen scripts without loosening everything, since default-src 'unsafe-inline' weakens every fetch type. Add an explicit script-src instead, so the relaxation is scoped to scripts.
Recommendation
Start from default-src 'self' as the catch-all, set the directives that never fall back explicitly, and tighten scripts with their own directive, inside a complete base policy:
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-endpointPair it with the endpoint declaration in a separate block:
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"default-src 'self' covers every fetch you did not name, while base-uri, form-action, and frame-ancestors are set directly because the fallback never reaches them. Script handling moves to script-src, so you can adopt a nonce without loosening the rest of the policy.
Reporting
When a request is blocked through the default-src fallback, the browser sends a csp-violation report naming the effective directive that was checked. Point the policy at a reporting endpoint to collect these and see which fetch types the fallback is catching before you tighten it.
Browser support
default-src is part of CSP Level 1 and is supported in every browser that implements CSP. It is stable and widely available.
FAQ
Does default-src cover every directive?
No. default-src is a fallback only for the fetch directives. It does not cover base-uri, form-action, frame-ancestors, sandbox, or the reporting directives, which stay unset unless you name them explicitly. A tight default-src 'self' does nothing for those, so set them yourself.
Is default-src 'self' enough for a CSP?
No. default-src 'self' is a reasonable floor, but on its own it allows same-origin inline scripts and does nothing for the document directives. For a strong policy, add a nonce or hash plus 'strict-dynamic' on script-src, object-src 'none', and base-uri 'none'.