Reference

Content-Security-Policy directives

Content Security Policy Level 3 defines twenty-three directives, in five groups: sixteen fetch directives that decide where scripts, styles, images, frames and connections may load from, two document directives, two navigation directives, two reporting directives of which report-uri is deprecated, and webrtc. Most fetch directives fall back to default-src when absent; the non-fetch directives never do, which is why default-src 'none' still allows the page to be framed by anyone. upgrade-insecure-requests is defined by a separate specification.

The directives of Content Security Policy Level 3, plus upgrade-insecure-requests from its own specification, with their fallback lists and whether a policy delivered in a meta element may use them.
DirectiveGroupWhat it controlsFalls back toIn a meta policy
default-srcFetchThe fallback for every other fetch directive that is not set.Nothing: it is the fallback.Allowed
child-srcFetchFrames and workers, through the fallback lists of frame-src and worker-src.default-srcAllowed
connect-srcFetchURLs contacted from script: fetch(), XMLHttpRequest, WebSocket, EventSource and sendBeacon.default-srcAllowed
font-srcFetchFonts loaded with @font-face.default-srcAllowed
frame-srcFetchThe URLs the page may load into its own frames and iframes.child-src, then default-srcAllowed
img-srcFetchImages and favicons.default-srcAllowed
manifest-srcFetchApplication manifests.default-srcAllowed
media-srcFetchAudio, video and text tracks.default-srcAllowed
object-srcFetchPlugin content loaded by object and embed.default-srcAllowed
script-srcFetchScripts, including inline scripts, inline event handlers and string evaluation such as eval().default-srcAllowed
script-src-elemFetchScript elements only, inline and external.script-src, then default-srcAllowed
script-src-attrFetchInline event handler attributes such as onclick.script-src, then default-srcAllowed
style-srcFetchStyle sheets, inline style elements and style attributes.default-srcAllowed
style-src-elemFetchStyle elements and linked style sheets only.style-src, then default-srcAllowed
style-src-attrFetchInline style attributes only.style-src, then default-srcAllowed
worker-srcFetchScripts run as Worker, SharedWorker or ServiceWorker.child-src, then script-src, then default-srcAllowed
base-uriDocumentThe URLs a base element may set as the document's base URL.NoneAllowed
sandboxDocumentApplies iframe-style sandbox restrictions to the page itself, with the same allow- keywords.NoneNot supported
form-actionNavigationThe URLs forms may submit to.NoneAllowed
frame-ancestorsNavigationWhich pages may embed this page in a frame; the modern replacement for X-Frame-Options.NoneNot supported
report-uriReportingA URL that receives violation reports. Deprecated in favour of report-to, and ignored when report-to is present.NoneNot supported
report-toReportingThe name of a reporting endpoint, defined through the Reporting API, that receives violation reports.NoneAllowed
webrtcOtherWhether WebRTC connections may be established: 'allow' or 'block'.NoneAllowed
upgrade-insecure-requestsDefined elsewhereRewrites the page's http:// subresource URLs to https:// before fetching them.NoneAllowed

How the fallbacks decide what a short policy allows

A fetch directive that is absent is not "allow everything": the browser walks its fallback list until it finds a directive that is present. `script-src-elem` falls back to `script-src`, then to `default-src`; `worker-src` goes through `child-src` and `script-src` before `default-src`; `frame-src` goes through `child-src`.

That is what makes `default-src 'self'` a meaningful one-line policy: every fetch directive the policy does not mention inherits it.

The document, navigation and reporting directives have no fallback. `default-src 'none'` does not restrict `form-action`, `base-uri` or `frame-ancestors`, so a strict-looking policy can still let any site frame the page or let an injected base element redirect every relative URL.

The split `-elem` and `-attr` directives exist so a policy can allow external scripts while forbidding inline event handlers, which a single `script-src` cannot express without `'unsafe-inline'`.

Several policies can apply at once — two `Content-Security-Policy` headers, or a header and a meta element — and each is enforced on its own. A request has to pass every one of them, so adding a second policy can only restrict further; it can never loosen the first.

What a meta element can and cannot carry

A policy can be delivered in the `Content-Security-Policy` response header or in a `<meta http-equiv>` element. The meta form is read only from the point the parser reaches it, so anything loaded before it is not covered.

CSP Level 3 excludes three directives from the meta form: `frame-ancestors`, `sandbox` and `report-uri`. The report-only variant of the header cannot be delivered in a meta element at all.

A site that relies on a meta policy for clickjacking protection therefore has none: `frame-ancestors` only works as a header.

What a scan reads in the policy

`security.csp` reads the `Content-Security-Policy` header of the entry page, or `Content-Security-Policy-Report-Only` when that is all the site sends. A missing policy is reported as a failure.

It then flags `'unsafe-inline'` and `'unsafe-eval'` wherever they appear, and a `*` source in `default-src` or `script-src`. A policy without those is reported as present; the scan does not evaluate each directive of the table against the page's real resources.

Framing protection is read separately by `security.x_frame_options`, which looks for the `X-Frame-Options` header. It does not read `frame-ancestors`, so a site protected only by that directive is reported as missing the header although browsers that support CSP do enforce the protection.

A policy delivered only in a meta element is not read by these checks, which look at response headers.

Frequently asked questions

Does default-src apply to frame-ancestors?
No. frame-ancestors, form-action, base-uri, sandbox and the reporting directives have no fallback. A policy of default-src 'none' still lets any site frame the page unless frame-ancestors is set.
Can I set frame-ancestors in a meta tag?
No. CSP Level 3 does not support frame-ancestors, sandbox or report-uri in a policy delivered by a meta element. Framing protection has to be sent as a response header.
Should I still use report-uri?
It is deprecated in favour of report-to, and ignored when report-to is present. The specification suggests sending both for compatibility with browsers that do not support report-to yet.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website