# Clickjacking protection is present

- **Pattern:** `ab-002529` (`site-health-check.security-posture.frame-protection`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002529
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002529)

## Why it matters

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.

## Severity rationale

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.

## Remediation

Add either `X-Frame-Options` or a CSP `frame-ancestors` directive — both protect against clickjacking, and they can coexist for broader browser coverage:

```nginx
# 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`:

```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.

## Detection

- **ID:** `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`.

---

## External references

- cwe CWE-1021
- owasp A05

Taxons: injection-and-input-trust

HTML version: https://auditbuffet.com/patterns/ab-002529
