CentralCSP
PoliciesContent-Security-PolicyDirectives

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:

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.

ValueStatusDescription
'none'✅ GoodBlocks every fetch the policy governs. Used alone.
'self'✅ GoodResources from your own origin only.
Host source✅ GoodA specific host such as cdn.example.com.
https:❌ RiskyAny origin over TLS, including for scripts through the fallback.
data:❌ RiskyExecutes as script through the fallback. Allow it on img-src or font-src instead.
blob:❌ Riskyblob: URLs execute as script through the fallback.
'nonce-...'✅ GoodPer-response random token; only meaningful for scripts and styles.
'sha256-...'✅ GoodDigest of an exact inline block; only meaningful for scripts and styles.
'strict-dynamic'✅ GoodApplies when the fallback governs scripts; host and scheme sources are then ignored.
'wasm-unsafe-eval'✅ GoodWebAssembly compilation only, narrower than 'unsafe-eval'.
'report-sample'✅ GoodAdds the first 40 characters of blocked inline content to reports.
'trusted-types-eval'✅ GoodAllows eval only with TrustedScript when Trusted Types are enforced. Recently became available across current Chrome, Firefox, and Safari.
'unsafe-inline'❌ RiskyAllows every inline script and style, including injected ones.
'unsafe-eval'❌ RiskyAllows eval(), new Function(), and string timers.
'unsafe-hashes'❌ RiskyLets hashes match inline event handlers, re-enabling that surface.
'inline-speculation-rules'🧪 ExperimentalInline speculation rules scripts. Chromium-led, not on the standards track.
'report-sha256' / 'report-sha384' / 'report-sha512'🧪 ExperimentalReport-only hash collection. Chromium-only.

You can combine:

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-endpoint

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

See also

Sources

On this page