Clickjacking is a deceptive attack where a malicious site overlays an invisible iframe of your application on top of seemingly innocent content, tricking users into clicking buttons or links they cannot see. The consequences range from unwanted social media likes to unauthorized fund transfers.
Two HTTP headers defend against clickjacking: the legacy X-Frame-Options and its modern successor, Content-Security-Policy: frame-ancestors. This article covers both and explains when to use each. For the full picture of security headers, see our complete security headers guide.
The attacker creates a page with an invisible <iframe> pointing to your application, positioned so that the user's click on the visible page actually hits a button inside the invisible iframe. Common attack scenarios include:
The attack works because the browser faithfully executes clicks on the framed page, including sending cookies and authentication tokens.
The X-Frame-Options header is the original defense against clickjacking. It accepts three values:
DENY — the page cannot be framed by any site, including your own.SAMEORIGIN — the page can only be framed by pages from the same origin.ALLOW-FROM uri — the page can only be framed by the specified origin. Deprecated: not supported in Chrome or Firefox.X-Frame-Options: DENYFor most sites, DENY is the correct choice. Use SAMEORIGIN only if your application intentionally frames its own pages (for example, a preview feature in a CMS).
The modern replacement is the frame-ancestors directive in Content Security Policy:
Content-Security-Policy: frame-ancestors 'none'Advantages over X-Frame-Options:
frame-ancestors 'self' https://trusted.example.comframe-ancestors https://*.example.comFor deep background on CSP, see Content Security Policy (CSP) Explained.
Yes. Set both X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none'. Modern browsers use frame-ancestors and ignore X-Frame-Options when both are present. Older browsers that do not support CSP fall back to X-Frame-Options. This provides maximum coverage.
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none'" always;If you have a full CSP, add frame-ancestors 'none' to your existing policy rather than setting a separate header.
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"Some applications legitimately need to be framed — embeddable widgets, payment forms, or content displayed inside a partner's site. In these cases:
frame-ancestors with explicit origins: frame-ancestors https://partner.example.comX-Frame-Options: SAMEORIGIN as a fallback (it cannot express multiple allowed origins, so this is a compromise).frame-ancestors * or omit the directive entirely.Use our X-Frame-Options testing tool to verify your header is set correctly. You can also audit all your security headers in one scan. A quick manual test: create an HTML file with <iframe src="https://yoursite.com"> — if the frame loads, you are vulnerable.
Clickjacking prevention is one piece of a broader security posture. Combine it with HSTS, a strong CSP, and proper cookie security for comprehensive protection.