Glossary
What is clickjacking — invisible traps that make you click hidden buttons
Clickjacking overlays a real page invisibly on top of an attacker's site so a logged-in user clicks 'hidden' buttons. How it works, and the real defense (CSP frame-ancestors and X-Frame-Options so your site can't be framed) — explained defensively, no attack steps.
"The button you clicked on purpose was actually a button on a hidden page underneath" — that's clickjacking. Here's how it works and how to reliably prevent it (no attack steps).
What gets targeted
Anything that is "one click, done, and valuable."
| Likely target | Why |
|---|---|
| Confirming a transfer/purchase | One click moves money |
| Settings change (visibility, connected apps) | Sets up later takeover or data access |
| OAuth / permission "Allow" | Silently approves an account link |
| Social follow / like / post | Abused for spread and like-farming |
Why it works
Browsers can load another site in an iframe and stack it on top. The attacker makes that iframe transparent (opacity 0), so the user only sees the decoy UI placed below. When the user clicks the "fake button," the real button layered directly above gets the click.
It resembles CSRF, but CSRF sends a request behind the scenes, while clickjacking makes the user operate the real screen — so CSRF tokens alone don't stop it.
Defense: the real fix is "can't be framed"
Set CSP frame-ancestors (most important)
Add Content-Security-Policy: frame-ancestors 'self' (only your own origin may frame you). If no one needs to embed you, 'none' is safest. List domains only for the partners you explicitly allow.
Add X-Frame-Options too (backward compatible)
For older clients, also send X-Frame-Options: DENY (or SAMEORIGIN). Belt-and-suspenders across old and new browsers.
Require a second step for critical actions
Gate transfers and permission grants behind re-auth, a confirm dialog, or an intent check — harder to drive through a silent overlay.
Make session cookies SameSite
SameSite=Lax/Strict curbs cross-site auto-sending. Not a complete clickjacking fix on its own, but it weakens the broader "action started from another site" class.
This site's view: one header line does the most — measure your own site first
Clickjacking defense isn't fancy code; it's one or two response-header lines that remove the foundation an overlay needs. Apply them site-wide at the framework or reverse proxy (Caddy/nginx) so nothing slips through. You can check whether frame-ancestors is actually live with the security-headers checker in This site's tools. "Thought I set it" — the missing header — is the most common failure.
Read next
- Glossary: What is CSRF · What is XSS
- Check: Free security tools (security headers checker)
FAQ
QWhat can clickjacking do?
A click the user makes 'on purpose' lands on a real page's button layered underneath. One-click critical actions get abused: money transfers, settings changes, granting permissions, social follow/like, consent buttons. It doesn't steal a password — it makes the already-logged-in user perform the action.
QWhat's the top defense?
Refuse to be embedded in another site's frame. Set the CSP frame-ancestors directive to 'self' (or only allowed domains) in your response headers, and add X-Frame-Options: DENY for backward compatibility. That removes the surface an overlay needs.
QIs JavaScript frame-busting enough?
No. Old 'break out if I'm in an iframe' scripts have many bypasses and don't help when JS is disabled. The real fix is server headers (frame-ancestors / X-Frame-Options) that tell the browser to refuse the embed.