frame-ancestors
The CSP frame-ancestors directive controls which origins may embed your page in a frame, the modern anti-clickjacking control.
Last update:
The frame-ancestors directive controls which origins are allowed to embed the
current page inside a
<frame>,
<iframe>,
<object>, or <embed>. It is the modern defense against clickjacking, where an
attacker loads your page in a hidden frame on their own site and tricks a user
into clicking something they cannot see.
Note that this directive is about who can frame you, the reverse of
frame-src,
which controls what your page is allowed to load into its own frames.
Prevent any site, including your own, from framing the page:
Content-Security-Policy: frame-ancestors 'none'Fallback chain
frame-ancestors has no fallback.
default-src
does not cover it, so a page with no frame-ancestors can be framed by anyone.
Values
frame-ancestors takes a source list of origins. Nonces and hashes do not apply,
they describe content, not an embedding origin.
| Value | Status | Description |
|---|---|---|
'none' | ✅ Good | No origin may embed the page, including the same origin. |
'self' | ✅ Good | Only the page's own origin may embed it. |
| Host or scheme source | ✅ Good | Allows the listed host source or scheme source to embed the page, for example a partner domain. |
You can list several ancestors. When the embedding chain does not match, the
browser refuses to render the page in the frame. Avoid a wildcard or a bare
scheme like https:, which lets any site frame your page and reopens the
clickjacking risk; list only the specific origins that have a real reason to
embed you.
Relationship to X-Frame-Options
frame-ancestors is the successor to the legacy
X-Frame-Options
header, and it is more expressive. The mapping is direct:
| X-Frame-Options | frame-ancestors equivalent |
|---|---|
DENY | frame-ancestors 'none' |
SAMEORIGIN | frame-ancestors 'self' |
ALLOW-FROM uri (obsolete) | frame-ancestors https://partner.example |
Where a browser supports both, frame-ancestors takes precedence over
X-Frame-Options. X-Frame-Options could never list more than one allowed origin
and its ALLOW-FROM form was dropped, so frame-ancestors replaces it. You can
still send X-Frame-Options alongside for very old clients, but frame-ancestors
is the control that matters today. We cover when to retire the legacy header in
clickjacking protection without a CSP header
and in legacy security headers to retire.
Examples
Allow only same-origin framing:
Content-Security-Policy: frame-ancestors 'self'Allow a specific partner to embed the page:
Content-Security-Policy: frame-ancestors 'self' https://partner.example.comSecurity notes
frame-ancestors works only as an HTTP response header. A <meta http-equiv> CSP
cannot carry it, the browser ignores it there. The same is true of
sandbox
and the reporting directives. Set frame-ancestors in your server or edge
configuration, not in markup.
The directive blocks clickjacking. In a clickjacking attack the victim's browser loads your real, logged-in page in a transparent frame layered over attacker content, so a click the user thinks lands on the attacker's button actually lands on your page (confirming a transfer, changing a setting, granting a permission). By restricting who may frame the page, you stop the page from rendering inside an attacker's document at all, which removes the attack surface.
Known bypasses and risks
frame-ancestors only governs framing. It does nothing about other navigation or
script behavior, so it is one control among several in a complete policy. It also
relies on the response actually carrying the header on every framed document, a
page served without it from some path or cache can still be framed, so apply it
consistently across the site.
Setting frame-ancestors 'none' on a page that is supposed to be embedded (a
widget, an OAuth consent screen, a documentation snippet) breaks that embedding.
Decide per page whether it should ever be framed, and by whom, then set the
directive to match. Run the policy through the
CSP evaluator to confirm the value is what you intend.
Recommendation
Ship frame-ancestors 'none' on pages that are never meant to be embedded, or
'self' if you frame your own pages, per the OWASP CSP cheat sheet.
Content-Security-Policy: frame-ancestors 'none'X-Frame-Options: DENYThe OWASP HTTP Headers cheat sheet
recommends sending X-Frame-Options: DENY alongside for old clients;
frame-ancestors takes precedence wherever both are supported.
Reporting
When the directive blocks a framing attempt, the browser emits a
csp-violation report
naming frame-ancestors as the effective directive. Wire delivery with the
report-to directive
and the Reporting-Endpoints header.
Browser support
frame-ancestors is part of CSP Level 2 and Level 3 and is widely supported
across current browsers. Where supported it supersedes X-Frame-Options.
FAQ
Should I use X-Frame-Options or frame-ancestors?
frame-ancestors is the modern, more expressive successor to X-Frame-Options,
and it wins wherever both are supported. Send both: frame-ancestors as the
control that matters today, and X-Frame-Options: DENY alongside for very old
clients. See the full comparison in
X-Frame-Options vs frame-ancestors.
Can I set frame-ancestors in a meta tag?
No. frame-ancestors works only as an HTTP response header. A <meta http-equiv> CSP cannot carry it, and the browser ignores it there, the same as
the sandbox and reporting directives. Set it in your server or edge
configuration on every framed document, not in the page markup.
frame-ancestors 'none' or 'self'?
'none' blocks all framing, including same-origin, so use it on pages that are
never meant to be embedded. 'self' allows only the page's own origin to frame
it, so use it when you embed your own pages. Any other origin listed must have a
real reason to embed you.
See also
- X-Frame-Options header
- frame-src
- sandbox
- default-src
- clickjacking protection without a CSP header
- Legacy security headers to retire