X-Frame-Options Header Not Set: Clickjacking Risk and Fix
X-Frame-Options Header Not Set: Clickjacking Fix
Browser Security

X-Frame-Options Header Not Set: Clickjacking Risk and Fix

An X-Frame-Options or “Missing Anti-clickjacking Header” finding means a browser-rendered page can potentially be embedded by another site unless a modern CSP frame-ancestors policy already blocks it. The correct fix depends on whether the page should never be framed, may be framed only by the same origin, or needs an explicit trusted-origin framing policy.

Framing controlZAP 10020-1
ZAP alert10020-1 · Passive
RiskMedium
Core concernClickjacking
Modern controlCSP frame-ancestors

An X-Frame-Options Header Not Set finding usually means the tested HTML page does not contain X-Frame-Options and the scanner did not detect an equivalent Content-Security-Policy: frame-ancestors ... restriction. Without a framing restriction, another site may be able to place the page in an invisible or deceptive frame and trick a user into interacting with it.

The important nuance is that the ZAP finding is really about anti-clickjacking protection, not loyalty to one header name. A modern CSP with an appropriate frame-ancestors directive can satisfy the security goal even when X-Frame-Options is absent. Remediation should therefore begin with the application’s legitimate framing model.

What Does “X-Frame-Options Header Not Set” Mean?

Scanner meaning

OWASP ZAP alert 10020-1 is a passive, release-status, medium-risk finding named Missing Anti-clickjacking Header. It looks for a valid framing defense, not only the literal X-Frame-Options header.

Security meaning

Without an effective framing restriction, an attacker-controlled site may be able to place a sensitive page in a transparent or disguised frame and trick a user into clicking controls they did not intend to activate.

Modern choice: use CSP frame-ancestors when you need explicit trusted parent origins. X-Frame-Options: DENY or SAMEORIGIN remains useful for simple policies and compatibility.

How Scanners Detect This Finding

Anti-clickjacking scanners inspect HTML responses for framing restrictions. Modern checks usually accept either X-Frame-Options or a CSP frame-ancestors directive, because the security goal is to stop untrusted framing rather than to require one particular legacy header.

This creates an important false-positive review step: if a scanner reports X-Frame-Options missing, verify whether a valid enforcing CSP already contains frame-ancestors. Conversely, a CSP that has no frame-ancestors directive does not automatically provide clickjacking protection just because another CSP directive exists.

Practical Security Scenario

Suppose a banking page contains a “Confirm transfer” button. An attacker can create a page that embeds the bank in a nearly transparent iframe, positions a decoy button over the real control, and persuades an authenticated user to click. The visible page belongs to the attacker, but the click lands on the legitimate bank application.

Framing restrictions prevent the browser from rendering the sensitive page inside an untrusted parent. They do not verify the transaction itself, so high-risk actions should still use authorization checks, transaction context, and where appropriate reauthentication or explicit confirmation.

Where This Control Should Be Applied

Focus anti-clickjacking policy on browser-rendered pages that contain meaningful user interaction. Public images, JSON APIs, and machine-to-machine endpoints are not typical clickjacking targets because the attack depends on deceiving a human inside a rendered interface.

Inventory legitimate embedding before choosing DENY or SAMEORIGIN. Enterprise portals, BI dashboards, embedded admin tools, identity products, and partner applications sometimes frame pages intentionally. If selected external parents are required, CSP frame-ancestors is the appropriate place to express those origins.

Why Missing Anti-Clickjacking Protection Matters

Clickjacking is a user-interface attack. An attacker loads a legitimate page inside a frame, overlays or positions other content around it, and induces the victim to click or type into the real application while believing they are interacting with something else.

The impact depends on what the framed page can do. A read-only public page may have little risk, while pages that approve payments, change account settings, grant permissions, or trigger privileged actions are more attractive targets.

Framing restrictions do not replace CSRF protections, reauthentication, transaction confirmation, or authorization. They specifically reduce the ability of untrusted origins to embed and visually manipulate your document.

X-Frame-Options vs CSP frame-ancestors

  • X-Frame-Options: DENY: Blocks the document from being framed by any origin.
  • X-Frame-Options: SAMEORIGIN: Allows framing by pages from the same origin.
  • ALLOW-FROM: Obsolete and not a reliable modern solution for allowing selected external origins.
  • frame-ancestors: The CSP directive that can express more flexible trusted ancestor rules and is the modern framing control.
  • Response header only: X-Frame-Options must be delivered as an HTTP response header; setting it in a META element does not provide compliant protection.

Related Ammune guides: Content Security Policy Header Not Set, HTTP security header not detected, and API authorization vs authentication.

Recommended Framing Examples

Choose one policy based on business requirements:

# Never allow framing
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'

# Same-origin framing only
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Deployment note: When a page must be framed by selected external origins, use CSP frame-ancestors with explicit trusted origins. Do not rely on the obsolete X-Frame-Options ALLOW-FROM directive.

Common Remediation Mistakes

  • Adding SAMEORIGIN without checking whether a legitimate cross-origin portal embeds the page.
  • Using ALLOW-FROM as though it were a portable modern control.
  • Setting X-Frame-Options in HTML <meta> instead of the response header.
  • Protecting only the home page while sensitive workflow pages remain frameable.
  • Treating an API JSON response the same as an interactive HTML document; clickjacking primarily concerns renderable user interfaces.
  • Assuming framing protection eliminates CSRF or authorization flaws.

How to Fix Missing Anti-Clickjacking Protection

1. Inventory legitimate embedding. Identify pages intentionally framed by your own portal, partner domains, identity products, dashboards, payment flows, support tools, or embedded applications. Do this before choosing a blanket policy.

2. Choose the simplest valid policy. Use DENY when framing is never needed, SAMEORIGIN for same-origin framing, or CSP frame-ancestors when selected external parents must be allowed.

3. Apply the policy to interactive HTML. Prioritize authenticated and state-changing pages. JSON APIs, images, and machine-to-machine endpoints are not the usual clickjacking target because the attack relies on a rendered user interface.

4. Test both denial and legitimate embeds. Attempt to frame the page from an untrusted origin and confirm the browser blocks it. Then test every approved portal or integration so remediation does not silently break a valid embedding flow.

5. Re-scan for framing quality issues. Check for duplicate or malformed X-Frame-Options values and verify that CSP actually includes frame-ancestors if CSP is your authoritative control.

Configuration Examples

Framing policy is a response-level control and can be applied at the application, proxy, gateway, or web server. Route-level application ownership is preferable when some pages must be framed and others must not. Avoid multiple intermediaries adding different X-Frame-Options values.

NGINX

add_header X-Frame-Options "SAMEORIGIN" always;
# Prefer a CSP frame-ancestors policy as the authoritative modern rule.

Apache

Header always set X-Frame-Options "SAMEORIGIN"

Application

For routes with different framing requirements, set CSP frame-ancestors at the application level so each page receives the intended ancestor allowlist.
Important: syntax can vary by software version and deployment model. Validate the generated response after every change rather than relying only on configuration-file appearance.

How to Test the Fix

  1. Inspect the final HTML response for X-Frame-Options and/or CSP frame-ancestors.
  2. Create a simple test page on another origin with an <iframe> pointing to the protected route and verify that the browser blocks framing when it should.
  3. Test legitimate embedded flows such as portals, dashboards, SSO helpers, support tools, payment widgets, and admin consoles.
  4. Confirm duplicate proxies are not sending contradictory X-Frame-Options values.
  5. Re-run the scanner and check for malformed or multiple X-Frame-Options findings.

A useful functional test is a small page on another origin containing an <iframe> pointed at the protected route. Browser console messages should confirm why the load was blocked. Test the same route from every approved embedding origin before declaring the change production-safe.

How to Think About Severity

ZAP rates Missing Anti-clickjacking Header as Medium. Actual impact is highest when the framed page contains authenticated, high-value actions such as changing account details, approving payments, granting permissions, or triggering administrative operations.

Anti-clickjacking headers do not replace authorization or transaction confirmation. Sensitive actions should still validate the authenticated user, object ownership, request context, and—where appropriate—require explicit reauthentication or confirmation. Framing policy prevents one UI deception technique; it is not a substitute for secure workflow design.

How Ammune Fits

Framing headers protect the browser presentation layer. Ammune focuses on what happens when the underlying APIs are called: whether access is expected, whether business flows are being automated or abused, and whether sensitive data is exposed.

This distinction matters because a clickjacking attempt ultimately causes legitimate-looking requests to reach the application. Strong authorization and runtime API monitoring remain important even when the browser successfully blocks untrusted framing.

Production Remediation Checklist

  • Inventory every legitimate frame/iframe integration before changing policy.
  • Use DENY when the page should never be framed.
  • Use SAMEORIGIN only when same-origin embedding is a real requirement.
  • Use CSP frame-ancestors for selected trusted external parent origins.
  • Do not use the obsolete ALLOW-FROM directive.
  • Apply the policy to interactive HTML, especially authenticated and state-changing pages.
  • Test an untrusted external frame and confirm the browser blocks it.
  • Test approved portals, SSO helpers, dashboards, and embedded workflows.
  • Remove duplicate or contradictory X-Frame-Options headers across proxies.
  • Re-run the scanner and review malformed/multiple-header alerts separately.

Frequently Asked Questions

What is the safest X-Frame-Options value?

DENY is the most restrictive when a page never needs framing. SAMEORIGIN is appropriate when same-origin framing is required.

Is X-Frame-Options obsolete?

It remains supported, but CSP frame-ancestors is the more flexible modern mechanism. Many deployments use frame-ancestors as the main policy and retain X-Frame-Options for compatibility.

Does X-Frame-Options stop CSRF?

No. It prevents or limits framing; it does not stop a cross-site request from being sent through other mechanisms.

Why does ZAP call this Missing Anti-clickjacking Header?

ZAP checks for a framing defense, not only the literal X-Frame-Options header. An appropriate CSP frame-ancestors policy can satisfy the underlying protection goal.

What is the ZAP alert ID?

Missing Anti-clickjacking Header is ZAP alert 10020-1.

Primary References

Protect the UI and the APIs It Drives

Anti-clickjacking policy protects how a page may be embedded. Ammune helps protect the APIs behind those user actions by analyzing runtime behavior, sensitive data, and abuse patterns.

© Ammune.ai — API security guidance for modern application environments.