A clickjacking attack puts your real site in a transparent frame over a page the attacker controls, so the click a user thinks they are making somewhere harmless lands on yours. One Content Security Policy directive shuts it down — and reporting tells you who is framing you before you switch it on.
Clickjacking does not compromise your site. It loads the real thing, in a real session, and stacks something over it — so the user is authenticated, the interface is yours, and every click is delivered to your application exactly as if they meant it. As OWASP puts it, a carefully arranged combination of stylesheets, frames and text boxes can leave someone believing they are typing into their bank when they are typing into an invisible frame the attacker controls. Nothing in your logs will look wrong, because from your side nothing was.
Because your page is loaded normally, the user's cookies and session come with it. A hijacked click can confirm a payment, grant a permission or approve a consent screen, and your application sees a legitimate request from a legitimate user.
There is no injected script, no malformed input and no anomaly to alert on. The framing happens entirely in the victim's browser, on a page you do not control, and leaves no trace on your infrastructure at all.
Partners embed dashboards, internal tools frame admin pages, documentation sites embed live examples. Blocking all framing without knowing the current picture is how a protection change becomes an outage for somebody you support.
The frame-ancestors directive controls which origins are allowed to embed your pages. Report URI collects the violation reports, so the list you end up enforcing is drawn from what actually happens rather than from memory.
Deploy the directive in report-only mode and every framing attempt that would have been refused is reported instead — naming the origin doing the embedding and the page of yours it framed. Most teams find a partner or an internal tool they had forgotten about, and occasionally something they had no idea existed.
Learn more about CSP Reporting →Move the directive to an enforcing policy and browsers simply will not render your page inside a document from an origin you did not permit. The protection happens in the browser, before any of your interface is drawn, so there is nothing for an attacker to overlay in the first place.
Learn more about Policy Watch →X-Frame-Options offered all or nothing: deny everything, or allow your own origin. Naming a specific partner was never reliably supported. frame-ancestors takes a list, so a business that genuinely needs to be embedded by three named partners can permit exactly those three and refuse everyone else — and unlike the old header, it reports.
One directive. No code. Reports start arriving from your first visitor.
30-day free trial · One directive · No code · Cancel anytime
The directive is short and its behaviour follows directly from what you list. These are the forms you will actually use.
| Value | What it means |
|---|---|
| frame-ancestors 'none' | No document anywhere may embed your page |
| frame-ancestors 'self' | Only your own origin may embed it |
| frame-ancestors 'self' https://partner.example | Your origin plus a named partner, and nobody else |
| Report-only policy | Framing still works; you are told what would have been refused |
| Enforcing policy | The browser refuses to render your page in a disallowed frame |
| Blocked URI in a report | The origin that attempted the framing, so you can identify it |
Unlike X-Frame-Options, this is evaluated per-page, so a public marketing site and an authenticated account area can carry different rules.
Clickjacking protection is a Content Security Policy directive, enforced by the browser. Nothing of ours runs on your pages and no traffic is routed through us — the browser refuses the framing and reports what it refused.
You don't need a full CSP to start. A report-only header carrying just this directive will build the picture without affecting anyone.
Content-Security-Policy-Report-Only: frame-ancestors 'self';
report-uri https://your-subdomain.report-uri.com/r/d/csp/reportOnly
Already running a policy? Add frame-ancestors to it. When the reports show only origins you recognise, move the directive to your enforcing header.
Clickjacking is among the simplest attacks to shut down, and the reason sites remain exposed is almost never the difficulty of the directive. It is the uncertainty about who might be relying on being able to frame you. Reporting settles that from real traffic instead of from institutional memory.
If you have no policy at all yet, the CSP Wizard will build one from your own reports, and the CSP Builder will let you edit it afterwards.
This is about who may embed your pages. It does not govern what your pages load, and it does not tell you what the framing site is doing — it is the embedding-control layer, and it works alongside the rest.
| frame-ancestors does | Pairs with |
|---|---|
| Controls who may embed your pages | Frame Watch for the reverse — which frames your own pages load |
| Reports every framing attempt refused | CSP for the rest of the policy around it |
| Protects authenticated actions from hijacked clicks | Passkeys Protection for credential ceremonies specifically |
| Replaces X-Frame-Options | Policy Watch for detecting when the header itself changes |
Together, these form the browser-native security layer that sits between your application and the code executing around it.