Skip to content

frame-ancestors

frame-ancestors specifies which parents may embed this page in a <frame>, <iframe>, <object> or <embed>. It is the CSP replacement for X-Frame-Options, and frame-ancestors 'none' is equivalent to X-Frame-Options: DENY.

It does not fall back to default-src. A page with default-src 'none' and no frame-ancestors is embeddable by anybody, which is exactly the configuration clickjacking needs.

It is checked against every ancestor, not just the immediate parent, so a nested frame chain fails if any link in it is disallowed.

Content-Security-Policy: frame-ancestors 'none';
Content-Security-Policy: frame-ancestors <source-expression-list>;
  • Embedding of this document by <frame>, <iframe>, <object> and <embed>.
  • What this page may embed - that is frame-src.

frame-ancestors has no fallback. If it is absent from the policy it restricts nothing, whatever default-src says.

Content-Security-Policy: frame-ancestors 'none'
  • 'none' unless you have a partner who embeds you, in which case list their origins. 'self' is right for an app that frames its own pages.
  • Keep X-Frame-Options: DENY alongside it for browsers that predate CSP Level 2. Where both are present, frame-ancestors wins.
  • 'unsafe-inline', 'unsafe-eval', nonces and hashes are not valid here. Only 'none', 'self', hosts and schemes are.

Under frame-ancestors https://partner.example, on partner.example:

<iframe src="https://app.example.com/embed"></iframe>

Under frame-ancestors 'none', the same markup anywhere - the frame stays blank:

<iframe src="https://app.example.com/embed"></iframe>
  • Widely available across browsers since January 2018.
  • Not supported in <meta> elements. It must come from an HTTP header.
Field Value
violatedDirective frame-ancestors
effectiveDirective frame-ancestors
blockedUri https://embedder.example/, (empty)
Issue title frame-ancestors blocking embedder.example
  • The report comes from your document - the one that refused to be framed - so documentUri is your page and blockedUri is the would-be embedder. That is the opposite way round from every fetch directive, and it is why a frame-ancestors issue is the one report that tells you about somebody else’s site.
  • Browsers vary in how much of the embedder’s URL they disclose, and some send an empty blockedUri. HeaderHawk records an empty value as the host unknown, so an issue titled frame-ancestors blocking unknown means the browser withheld the ancestor, not that the ancestor was missing.
  • Real traffic here is worth reading: it is either a partner you forgot to allow, or somebody framing your site who should not be.

Point your policy’s report-uri at your site’s HeaderHawk endpoint and the violations above arrive in the dashboard, grouped as described. The Quick Start sets that up in five minutes, and the integration guides cover the header syntax for each platform.