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.
| Option | When it wins | Watch-out | Takeaway |
|---|---|---|---|
| frame-ancestors 'none' | Brochure, blog, login, docs that must not be framed | Breaks a same-origin iframe you actually shipped | Default for public marketing HTML |
| frame-ancestors 'self' | First-party tools iframe this origin on purpose | Any same-origin XSS can frame you too | Match X-Frame-Options SAMEORIGIN |
| Origin allowlist | One partner must embed one route | Copying that list onto /login | Scope by path; XFO cannot say the same thing |
| Missing frame-ancestors | Never as a plan | Relying on XFO forever, or on COOP | Ship 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 nowFAQ
- 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.