Clickjacking embeds your site invisibly inside an attacker-controlled iframe. A user sees the attacker's page, but their clicks land on your site's buttons — authorizing transfers, changing account settings, or submitting forms without knowing. CWE-1021 (UI Redress Attack) and OWASP A05 (Security Misconfiguration) both classify missing frame protection as a preventable failure. The fix is cheap: one header. Without it, any page on your site that performs sensitive actions is vulnerable to this class of social-engineering attack targeting legitimate authenticated sessions.
Low because clickjacking requires the victim to be tricked into visiting a malicious page, reducing realistic attack surface, but zero mitigation headers make it trivially exploitable when targeted.
Add either X-Frame-Options or a CSP frame-ancestors directive — both protect against clickjacking, and they can coexist for broader browser coverage:
# nginx — both headers
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
In Next.js next.config.js:
{ key: 'X-Frame-Options', value: 'DENY' }
Use DENY if your site never embeds itself in iframes. Use SAMEORIGIN if it needs to be framed from the same origin (e.g., admin embedded in a dashboard). CSP frame-ancestors takes precedence in modern browsers; X-Frame-Options covers older ones.
ID: site-health-check.security-posture.frame-protection
Severity: low
What to look for: Enumerate all clickjacking protection mechanisms in the response: check for X-Frame-Options header (must be DENY or SAMEORIGIN), and check the Content-Security-Policy header for a frame-ancestors directive. Count how many of these 2 protection mechanisms are present.
Pass criteria: At least 1 of the following 2 protections is present: (a) X-Frame-Options header with value DENY or SAMEORIGIN, or (b) CSP header contains a frame-ancestors directive that is not set to *. Report which mechanism(s) were found.
Fail criteria: Neither X-Frame-Options header nor a CSP frame-ancestors directive is present in the response.
Skip (N/A) when: The response is a redirect (3xx status) rather than a final document response.
Detail on fail: "No clickjacking protection — missing both X-Frame-Options and CSP frame-ancestors"
Remediation: Clickjacking embeds your site in a hidden iframe to trick users into clicking. Prevent it with either header:
X-Frame-Options: DENY
Or the modern CSP approach:
Content-Security-Policy: frame-ancestors 'self'
In next.config.js headers(), add X-Frame-Options: DENY. Both can coexist — browsers that support CSP frame-ancestors will use it; older browsers fall back to X-Frame-Options.