Clickjacking Defence: Past X-Frame-Options
Cybersecurity
X-Frame-Options is legacy. CSP frame-ancestors is the modern answer, with edge cases for partner integrations and PDF viewers. Get the layering right or your clickjacking defence is theatre.
By Arjun Raghavan, Security & Systems Lead, BIPI · September 25, 2024 · 6 min read
A government services portal we audited had X-Frame-Options: SAMEORIGIN on every page. Compliance tick, audit pass, three years of clean reports. We framed their account deletion endpoint inside our test page on a different origin. It loaded. Turns out a CDN configuration change six months prior had stripped the header for a specific path, and nobody noticed because no automated test checked.
Clickjacking on account deletion isn't subtle. We demoed a UI where users 'clicked to claim a prize' and lost their accounts. The fix was straightforward. The lesson was that header-based defences need monitoring, not just configuration.
Why X-Frame-Options is legacy
X-Frame-Options was a hack: a single header with three valid values (DENY, SAMEORIGIN, ALLOW-FROM origin). ALLOW-FROM was deprecated because it didn't support multiple origins and had inconsistent browser support. So in practice teams used DENY or SAMEORIGIN, which is too coarse for any real-world business that needs partner embedding.
Content Security Policy's frame-ancestors directive replaces XFO with proper expressiveness: multiple origins, wildcards (with care), and deny-by-default semantics. All modern browsers support it. The reason XFO is still everywhere is inertia and audit checklists that haven't been updated.
What frame-ancestors looks like in practice
Default policy for most pages: 'frame-ancestors none' or 'frame-ancestors self'. Sets the don't-frame-me posture clearly. For pages that need to be embedded by specific partners, list them: 'frame-ancestors self https://partner1.com https://*.partner2.com'. Wildcards are a takeover risk if the partner has dangling subdomains, so audit before allowing them.
Both frame-ancestors and X-Frame-Options should ship together. If a browser supports CSP, frame-ancestors wins. If something old or weird hits XFO, you have a fallback. The cost of double-shipping is one extra header per response.
Edge cases that bite
- PDF viewers: some browsers frame PDFs with their own viewer. frame-ancestors blocks this if not configured for the PDF route
- Embedded checkout flows (Stripe, PayPal): your page may need to frame their domain, which is allowed by default; the issue is if their flow needs to frame you back
- Mobile WebView: some apps frame their own login pages; frame-ancestors must permit the app's loader URL
- Marketing iframes: third-party widgets that load your blog inline (rarely necessary, often misused)
Beyond the header
CSP frame-ancestors prevents framing entirely. But sensitive actions inside your own pages still need clickjacking-aware UX. Two-step confirmations on destructive actions (account delete, password change, money transfer). Rate limits that flag rapid-fire automated clicks. Re-authentication prompts for high-impact operations.
These are defence-in-depth. If a clever attacker finds a frame-ancestors bypass (browser bug, double-key entry through a service worker, etc), the second layer slows them enough that the first one gets patched before damage is done.
Operational checklist
- Audit every public-facing route for frame-ancestors and XFO
- Default to 'none' or 'self' unless there's a documented business reason
- Add automated tests that fail if either header is missing on critical paths
- Monitor CSP violations; clickjacking attempts often show up as frame-ancestors violations from unexpected origins
- Sensitive actions get explicit confirmation UI even with framing locked down
Clickjacking is a classic bug class with a clean modern fix. The reason it still ships is operational drift: headers added once, not monitored, lost in a CDN config change. The fix is automated testing, not better headers.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.