How to restrict frame-src in a Content Security Policy?

csp:missing-frame-src page

The issue

A policy that doesn’t restrict frames lets anything injected into the page embed any site in an <iframe>. An attacker who can add markup, through a compromised script or an unescaped field, can place a fake login form or payment page inside yours, under your address bar. Nothing changes for visitors until it’s used.

The cause is a policy written for scripts and styles that never covers frames. Without frame-src, a browser falls back to child-src, then default-src; when none of them is set, frames are unrestricted.

Scope

Each response’s Content-Security-Policy header is checked, including every policy when it carries several. frame-src controls what your page embeds. It’s a different directive from frame-ancestors, which controls who can embed your page; see clickjacking.

How to check you have it

  • In probeo: csp:missing-frame-src when no policy sets frame-src, child-src or default-src, and csp:frame-src-wildcard when every policy that does allows *, https: or http:. Both are graded minor.
  • By hand: run curl -sI https://example.com/ | grep -i content-security-policy and look for frame-src, then child-src, then default-src, in that order.
  • With a tool: Google’s CSP Evaluator reads a pasted policy and flags broad sources.

The fix

Set frame-src to the origins your pages actually embed, or to 'none' if they embed nothing.

List each embed by its exact origin: a video player, a map, a payment form. A default-src 'self' covers frames too, but a frame-src of its own keeps the list of embeds readable and separate from the rest of the policy.

Content-Security-Policy: default-src 'self'; frame-src https://www.youtube-nocookie.com https://js.stripe.com; frame-ancestors 'self'

Done when: every policy restricts frames to named origins or 'none', and the check above comes back clean.

Do not

  • Do not use *, https: or http: in frame-src.
  • Do not rely on frame-ancestors to restrict what your page embeds; it controls the opposite direction.
  • Do not add an embed’s origin without checking every page that loads it.

FAQ

What’s the difference between frame-src and frame-ancestors?

frame-src decides which sites your page may show in a frame. frame-ancestors decides which sites may show your page in a frame. A policy needs both to cover embedding in each direction.

Does default-src count?

Yes. Probeo, like the browser, treats child-src and then default-src as the frame restriction when frame-src isn’t set. A policy with default-src 'self' isn’t reported as missing frame-src.

Is https: really as broad as *?

For frames, nearly. It allows any site served over HTTPS, which is almost every site, so probeo reports it the same way.

Which product detects this

Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.