In one paragraph
A missing X-Frame-Options header can leave a page open to embedding unless another effective control, such as CSP frame-ancestors, restricts it. Unwanted framing can enable clickjacking against authenticated interfaces. Choose whether the page may be framed by nobody, its own origin, or specific partners, then configure response headers and test both permitted and prohibited embedding in a browser.
Why it matters
Clickjacking places a real interface inside a frame controlled by another page. The attacker can disguise its position or appearance so a visitor activates something different from what they intended. The page and session may be genuine; the attack exploits how the surrounding interface is presented.
X-Frame-Options provides two useful values. DENY prevents framing, including same-origin framing. SAMEORIGIN permits it only when the ancestor context meets the same-origin requirement. Another subdomain is not the same origin merely because your business owns it.
For explicit partner allowlists, use the frame-ancestors directive in an enforcing Content-Security-Policy response header. Modern browsers use an applicable enforced frame-ancestors policy instead of X-Frame-Options. Legacy fallback behaviour still matters if your supported clients do not implement CSP, so make deliberate choices rather than claiming contradictory headers can never matter.
How WebAuditOS evaluates this finding
The supplied rule inspects HTML response headers. Presence of X-Frame-Options passes regardless of its value. Without it, a recognised restrictive CSP frame-ancestors can also pass; an unrestricted wildcard ancestor policy does not satisfy that protection path. If neither control is present, the result fails. Non-HTML and unavailable responses are not graded.
The presence-only X-Frame-Options test has an important limitation: an invalid value can pass without creating effective browser protection. The documented CSP analysis can also miss overly broad scheme sources such as https:. Read the actual policy, not just the pass label. A recognised header does not certify clickjacking resistance in every interface or supported browser.
How to fix it
- Inventory legitimate framing. Check your own dashboards, cross-subdomain previews, payment interfaces, partner portals, and widgets sold for customer embedding. Assign a policy by route where requirements differ.
- For a page that should never be embedded, use an enforcing response policy such as:
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY
If a CSP already exists, integrate the directive into that policy deliberately. Multiple enforced policies all apply; adding a second permissive policy cannot loosen an existing restrictive one.
- For same-origin framing, a corresponding setup is:
Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN
Use the origins actually required, not the informal idea of the same company or the same registrable domain.
- For a partner, configure a specific CSP source list, for example:
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com
X-Frame-Options cannot represent a modern multi-origin allowlist. ALLOW-FROM is obsolete and ignored by current browsers. Decide whether a restrictive legacy fallback should block the partner in older clients, or whether another supported deployment design is needed.
- Send the policy as an HTTP response header on the page being embedded. A meta http-equiv element does not enforce X-Frame-Options, and frame-ancestors also cannot be delivered through a CSP meta tag. A Report-Only CSP does not block unwanted framing.
- Test from a controlled page on an allowed origin and another on a prohibited origin. Include nested framing where your integration uses it: frame-ancestors considers the ancestor chain. Inspect the browser Console for the reason an iframe was blocked.
- Verify final public headers after CDN and proxy processing, and rescan the affected HTML pages. Keep regression tests for key embeds so a future global security-header change does not silently break them.
What the fix can break
A global DENY or SAMEORIGIN policy can disable legitimate external embeds, including widgets and cross-subdomain application screens. The browser blocks rendering, while server uptime checks may still look healthy.
A policy allowing only the immediate partner can fail if another unapproved ancestor wraps that partner's frame. Test the actual embedding chain, not a simplified demo with a single iframe.
Do not weaken every page to accommodate one public widget. Scope the exception to the intended endpoint or host, and keep sensitive account screens under the narrower policy. Framing controls supplement secure actions and CSRF protections; they are not a substitute for authorisation.
Questions
Do I need X-Frame-Options if frame-ancestors is already enforced?
Not for browsers that support and apply that directive. X-Frame-Options can provide a legacy fallback, but choose its behaviour intentionally for your supported clients.
Can I allow a partner with ALLOW-FROM?
Do not rely on it. The value is obsolete. Use CSP frame-ancestors for supported explicit-origin policies and test the target browsers.
Why does an invalid header pass WebAuditOS?
The supplied X-Frame-Options path tests presence rather than validity. A green finding is therefore not proof that the browser enforces the intended restriction.
What should I review next?
Review Content-Security-Policy and the security headers guide. Configure frame-ancestors explicitly; it does not inherit from default-src.