Clickjacking
debt(d5/e1/b3/t5)
Closest to 'specialist tool catches' (d5). The term's detection_hints.tools lists semgrep, lighthouse, and owasp-zap — all specialist security/audit tools that scan for missing X-Frame-Options or CSP frame-ancestors headers. Standard linters won't catch this; you need SAST or security-focused scanners.
Closest to 'one-line patch' (e1). The quick_fix is literally adding a single header call: header('X-Frame-Options: DENY') or the CSP equivalent. This is a one-line fix per response, and can be applied globally via middleware with minimal effort.
Closest to 'localised tax' (b3). Applies only to web contexts per applies_to. Once you add the header globally (via middleware or framework config), the burden is minimal. However, common_mistakes notes you must remember to apply it to all pages, creating a small ongoing tax when adding new endpoints.
Closest to 'notable trap' (t5). The misconception field explicitly states that developers believe JavaScript frame-busting scripts prevent clickjacking, when in fact they're easily bypassed via iframe sandbox attributes. This is a documented gotcha that most security-aware devs eventually learn, but the 'obvious' JS solution doesn't work.
Also Known As
TL;DR
Explanation
Clickjacking (UI redressing) loads a legitimate site in a transparent iframe positioned over a decoy page. The victim thinks they are clicking a harmless button on the attacker's page but are actually interacting with hidden elements on the legitimate site — liking posts, transferring funds, or changing settings. Prevention: set the X-Frame-Options: DENY (or SAMEORIGIN) response header, or use the Content-Security-Policy frame-ancestors directive. PHP: header("X-Frame-Options: DENY");
How It's Exploited
<iframe src="https://bank.com/transfer" style="opacity:0;position:absolute"></iframe>
<button>Claim prize!</button>
<!-- Click on 'Claim prize' actually clicks Transfer button on bank site -->
Common Misconception
Why It Matters
Common Mistakes
- Not setting X-Frame-Options or CSP frame-ancestors header — the page can be framed by anyone.
- Using X-Frame-Options: ALLOWALL which provides no protection.
- Implementing only JavaScript frame-busting code which is easily bypassed by sandbox attributes on the iframe.
- Forgetting to apply the header to all pages — attackers only need one frameable sensitive action.
Code Examples
// Missing frame protection header — page can be embedded in any iframe:
header('Content-Type: text/html');
// Should add: header('X-Frame-Options: DENY');
// Or: header("Content-Security-Policy: frame-ancestors 'none'");
// Prevent your page from being embedded in an iframe on another domain
header('X-Frame-Options: DENY');
// Or allow only same origin:
header('X-Frame-Options: SAMEORIGIN');
// Modern equivalent via CSP:
header("Content-Security-Policy: frame-ancestors 'none';");
// frame-ancestors 'self' — same as SAMEORIGIN but more flexible