CSP frame-ancestors Restricts Who Can Embed a Page
A web page can be security-sensitive even when an attacker cannot read its DOM. If another site can place that page inside a transparent or carefully positioned frame, the attacker may arrange visible controls so a user interacts with the framed application while believing they are interacting with something else. This class of UI redressing is commonly associated with clickjacking.
The Content Security Policy directive frame-ancestors gives the framed response control over that boundary. Instead of trusting the embedding page to behave safely, the protected response declares which ancestors are permitted to contain it.
The protected response sets the embedding boundary
A page that must never appear inside a frame can return:
Content-Security-Policy: frame-ancestors 'none'A page that may be framed only by documents from its own origin can use:
Content-Security-Policy: frame-ancestors 'self'A service that intentionally supports a specific external portal can name that origin:
Content-Security-Policy: frame-ancestors 'self' https://portal.example.netThe decision belongs to the resource being embedded. JavaScript in the parent does not grant permission to bypass the policy, and markup in the child does not need to cooperate after the browser receives the response header.
This makes the directive suitable for login screens, administrative interfaces, account settings, payment flows, and other pages whose controls should not appear inside arbitrary embedding contexts. The correct source list still depends on the product architecture; a page that is intentionally embedded by partners needs a different policy from a standalone console.
Every ancestor in a nested chain matters
Framing can involve more than one level. A top-level document may contain an intermediate frame, which then embeds the protected page.
top.example
|
+-- middle.example
|
+-- protected.exampleFor protected.example, allowing only middle.example is not enough when the top-level ancestor is outside the permitted set. The browser evaluates the ancestor chain against the directive. An ancestor that does not match causes the protected resource to be blocked from that nested context.
This property closes a useful gap in designs that inspect only the immediate parent. An otherwise approved intermediary cannot silently turn itself into a framing bridge for an arbitrary top-level site unless the protected policy also permits that ancestor arrangement.
frame-ancestors and frame-src control opposite directions
The similar names can hide an important distinction.
frame-ancestors controls which ancestors may embed the current response. It protects the current document from being placed inside unwanted framing contexts.
frame-src controls which frame resources the current document may load as children. It limits outbound framing initiated by the current document.
A policy can need both:
Content-Security-Policy:
frame-ancestors 'self' https://portal.example.net;
frame-src 'self' https://widgets.example.orgThe first directive constrains who may contain the page. The second constrains what the page may contain in frames. Tightening one does not substitute for the other.
default-src does not supply a fallback
Many CSP fetch directives can inherit a restriction from default-src when their own directive is absent. frame-ancestors does not use that fallback.
This policy does not prohibit other sites from framing the response merely because default-src is restrictive:
Content-Security-Policy: default-src 'none'A deployment that intends to block framing needs an explicit frame-ancestors directive:
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'That detail matters in compact policies. A strong fetch policy and a strong embedding policy are separate controls even when both are delivered in the same CSP header.
The directive belongs in the HTTP response header
frame-ancestors is not a policy that can be added reliably through a CSP <meta> element. The browser needs the embedding decision as part of the response policy for the protected resource.
That also affects infrastructure ownership. If an application relies on a reverse proxy, CDN, framework middleware, or web server to emit security headers, the final response must preserve the intended directive. A template-only change is not an equivalent deployment.
Routes deserve explicit review as well. A global header may fit a standalone application, while a product with intentionally embeddable widgets may need narrowly scoped exceptions. Broadly removing the directive for the entire host to support one widget expands the framing surface of unrelated pages.
X-Frame-Options covers a narrower policy model
X-Frame-Options predates CSP and commonly appears as either:
X-Frame-Options: DENYor:
X-Frame-Options: SAMEORIGINThose values cover two common cases: no framing or same-origin framing. frame-ancestors can express a list of permitted origins and evaluates the ancestor chain as part of CSP processing.
Systems that retain X-Frame-Options for older clients should keep its intent aligned with the CSP policy rather than treating two contradictory headers as independent access-control layers. Current policy design should center on frame-ancestors where the required browser set supports it.
The obsolete ALLOW-FROM form of X-Frame-Options is not a portable replacement for a CSP allowlist.
Framing control is not authorization
Blocking hostile framing removes one path for tricking a user into activating controls. It does not decide whether a request is authorized.
A state-changing endpoint still needs authentication, authorization, appropriate HTTP method semantics, and request-forgery defenses where applicable. A page can also contain DOM injection or script execution flaws even when no external site can frame it.
The boundary is therefore precise: frame-ancestors governs embedding. It does not sanitize HTML, validate user intent, secure cookies, or replace server-side checks.
That precision is useful during review. For each response, the relevant question is whether the page should be embeddable at all and, if so, which complete ancestor arrangements are legitimate. Encoding that answer in the response policy gives the browser a direct rule to enforce before an unapproved framing context can present the protected interface.