Clickjacking & CSP frame-ancestors
debt(d5/e1/b3/t5)
Closest to 'specialist tool catches' (d5). The term's detection_hints.tools lists owasp-zap, lighthouse, and semgrep — all specialist security/audit tools that can detect missing frame-ancestors or X-Frame-Options headers. These aren't default linters but dedicated security scanners.
Closest to 'one-line patch' (e1). The quick_fix is literally 'Add Content-Security-Policy: frame-ancestors 'none'' — a single header addition that can be done in one line of code or server configuration.
Closest to 'localised tax' (b3). The applies_to shows this is web-context only, and setting CSP headers is typically done in one place (middleware, server config, or a base controller). Once set, it doesn't impose ongoing maintenance burden on the rest of the codebase.
Closest to 'notable trap' (t5). The misconception explicitly states developers believe 'X-Frame-Options and CSP frame-ancestors do exactly the same thing' when frame-ancestors actually overrides X-Frame-Options in modern browsers. Common mistakes include using X-Frame-Options alone thinking it's sufficient, or not understanding browser prioritisation between the two headers. This is a documented gotcha most security-aware devs eventually learn.
Also Known As
TL;DR
Explanation
Clickjacking (UI redressing) embeds a target site in a transparent iframe, positioned over a decoy page. The victim believes they are clicking the decoy UI but actually interact with the hidden target — completing a purchase, changing a password, or granting OAuth permissions. The modern defence is the Content-Security-Policy frame-ancestors directive: frame-ancestors 'none' disallows all framing; frame-ancestors 'self' permits same-origin only; frame-ancestors https://trusted.com restricts to named origins. X-Frame-Options (DENY or SAMEORIGIN) is the legacy equivalent supported by older browsers. CSP frame-ancestors takes precedence where supported and is more granular. PHP: add both headers in a middleware for defence-in-depth.
Common Misconception
Why It Matters
Common Mistakes
- Using X-Frame-Options DENY without also setting CSP frame-ancestors — older header is ignored by modern browsers in some contexts.
- Setting frame-ancestors 'self' when the page legitimately needs to be embedded by a partner domain — too restrictive.
- Not setting frame-ancestors at all when X-Frame-Options is the only protection — some browsers prioritise CSP.
- Deploying frame-ancestors only on sensitive pages and missing others that trigger sensitive actions.
Code Examples
// Only X-Frame-Options — no CSP frame-ancestors:
header('X-Frame-Options: DENY');
// Modern browsers may ignore this if CSP is present without frame-ancestors
// Complete protection:
header('X-Frame-Options: DENY'); // Legacy browsers
header("Content-Security-Policy: frame-ancestors 'none'"); // Modern browsers
header("Content-Security-Policy: frame-ancestors 'none'");
header('X-Frame-Options: DENY'); // legacy fallback