RoastMyOpsec

Safety

CSP frame-ancestors none vs self for Clickjacking

December 7, 2022

CSP frame-ancestors none vs self is who may put your document in a frame: 'none' matches X-Frame-Options DENY (no parent, including your own origin), and 'self' matches SAMEORIGIN so same-origin tools may iframe the page. Most marketing homepages, blogs, and login HTML should ship 'none' unless a first-party dashboard actually frames that route; a named partner origin is a third option X-Frame-Options cannot express well. RoastMyOpsec treats framing as present if X-Frame-Options or CSP frame-ancestors appears — it does not fail 'self', prefer 'none', or load clickjacking proofs.

The practical difference

frame-ancestors is the modern framing control and, in supporting browsers, overrides X-Frame-Options when both are set. 'none' is the brochure default. 'self' is for same-origin admin shells, style guides, or help widgets that iframe your own HTML. Listing https://partner.example is for one route that must be embedded — not a site-wide gift.

X-Frame-Options remains the compatibility belt: DENY with 'none', SAMEORIGIN with 'self'. ALLOW-FROM is not a reliable modern control. iframe sandbox on children you include is the opposite direction and does not stop others from framing you.

How to choose based on what you shipped

Public marketing origin with no first-party iframe of itself: frame-ancestors 'none' and X-Frame-Options DENY on HTML. App shell that frames its own routes: 'self' and SAMEORIGIN, scoped to those routes if the brochure must stay unframed. Partner embed: allowlist that origin on the embeddable path only.

Do not weaken the whole site because one status widget needed a parent. COOP is opener isolation, not clickjacking control.

OptionWhen it winsWatch-outTakeaway
frame-ancestors 'none'Brochure, blog, login, docs that must not be framedBreaks a same-origin iframe you actually shippedDefault for public marketing HTML
frame-ancestors 'self'First-party tools iframe this origin on purposeAny same-origin XSS can frame you tooMatch X-Frame-Options SAMEORIGIN
Origin allowlistOne partner must embed one routeCopying that list onto /loginScope by path; XFO cannot say the same thing
Missing frame-ancestorsNever as a planRelying on XFO forever, or on COOPShip CSP framing; keep XFO as a belt

When frame-ancestors 'self' still wins

'self' still wins when your own origin frames dashboards, legacy admin, or a design-system preview and you would rather not split hosts. It does not win as a 'maybe we will embed later' default on a campaign landing page.

'none' still wins on login and checkout HTML even if the marketing blog is 'self'. Split the header by route at the edge. A roast that only sees the homepage cannot certify /app.

Common mistakes

The first mistake is frame-ancestors 'self' on the marketing homepage because a forgotten CMS preview used an iframe once.

The second mistake is CSP without frame-ancestors, assuming default-src covers parents — it does not.

The third mistake is DENY in X-Frame-Options and 'self' in CSP, so modern browsers and old ones disagree.

What a URL roast can prove

The free header check flags framing as missing when the document has neither X-Frame-Options nor a frame-ancestors directive in CSP. It does not distinguish 'none' from 'self', does not parse iframe sandbox, and does not score COOP. A clean framing signal means a control was present on that response, not that clickjacking was tested. CSP quality, HSTS, Referrer-Policy, nosniff, and Permissions-Policy are separate header findings. No exploit payloads, no GPC score, no HSTS preload submission.

Free audit the URL you own

RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.

Free audit now

FAQ

Should a marketing site use frame-ancestors none or self?
Use 'none' unless a same-origin tool actually iframes the page. 'self' is for first-party frames, not a future maybe.
Does RoastMyOpsec fail frame-ancestors 'self'?
No. Framing is a presence check (X-Frame-Options or frame-ancestors). 'self' satisfies it. Match XFO so CDNs do not disagree.
Does 'self' stop clickjacking from other sites?
It stops other origins from framing you. It does not stop a same-origin page you did not intend to be a parent. Use 'none' when no parent should exist.

Sources

Related guides