Should I use X-Frame-Options or CSP frame-ancestors?

x_frame_options_vs_csp_frame_ancestorsglobal

X-Frame-Options and Content-Security-Policy frame-ancestors both control whether a page can be embedded in an iframe. The frame-ancestors directive is more flexible and is the modern replacement. When both are present, browsers that support CSP Level 2 or higher ignore X-Frame-Options.

What’s Happening

The response includes either an X-Frame-Options header, a Content-Security-Policy header with frame-ancestors, or both. X-Frame-Options is a legacy header that supports only three values: DENY, SAMEORIGIN, and ALLOW-FROM. The frame-ancestors directive allows more granular control, including multiple origins and wildcard patterns. When both mechanisms are present, modern browsers prioritize frame-ancestors and ignore X-Frame-Options.

Why It Matters

X-Frame-Options is limited. It cannot allow embedding by multiple specific origins. It does not support flexible origin patterns. The ALLOW-FROM directive is deprecated and not supported by most modern browsers. Using X-Frame-Options alone creates ambiguity for teams managing embedding policies across multiple environments or partners. The frame-ancestors directive provides clarity and is the standard mechanism for modern browsers.

The Correct Change

  • Use the Content-Security-Policy frame-ancestors directive. Define embedding rules explicitly and with the necessary level of granularity.
  • If the page should not be embedded at all, set frame-ancestors ‘none’.
  • If the page should only be embedded by the same origin, set frame-ancestors ‘self’.
  • If the page should be embedded by specific origins, list them explicitly in the frame-ancestors directive.
  • Retain X-Frame-Options only if legacy browser support is required. Set it to DENY or SAMEORIGIN depending on the embedding policy. Do not rely on ALLOW-FROM.
  • Once frame-ancestors is deployed and verified, remove X-Frame-Options to eliminate redundancy and potential conflict.

Verification

  • The Content-Security-Policy header includes a frame-ancestors directive.
  • The frame-ancestors directive accurately reflects the intended embedding policy.
  • X-Frame-Options is either removed or set to a compatible fallback for legacy browsers.
  • The page behaves correctly in browsers that support CSP Level 2 or higher.

Takeaway

  • X-Frame-Options is a legacy header with limited functionality.
  • The frame-ancestors directive provides more flexible and explicit control.
  • Modern browsers prioritize frame-ancestors and ignore X-Frame-Options when both are present.
  • The correct approach is to use frame-ancestors and optionally retain X-Frame-Options for legacy support.

FAQ

What is the difference between X-Frame-Options and frame-ancestors?

X-Frame-Options supports only three values and cannot specify multiple origins. frame-ancestors supports explicit origin lists, wildcard patterns, and more granular control.

Do browsers support both mechanisms?

Yes, but modern browsers that support CSP Level 2 or higher prioritize frame-ancestors. If frame-ancestors is present, X-Frame-Options is ignored.

Should both headers be set?

Only if legacy browser support is required. Set X-Frame-Options as a fallback for older browsers that do not support frame-ancestors.

Can X-Frame-Options allow embedding by multiple origins?

No. The ALLOW-FROM directive only supports a single origin and is deprecated. Most browsers do not honor it.

What does frame-ancestors ‘none’ do?

It prevents the page from being embedded in any iframe, frame, or object. This is equivalent to X-Frame-Options: DENY.

Should X-Frame-Options be removed once frame-ancestors is deployed?

Yes, unless legacy browser support is explicitly required. Removing it eliminates redundancy and potential conflict.

The fix

Use CSP frame-ancestors instead of X-Frame-Options for embedding control.

Done when: The Content-Security-Policy header includes a frame-ancestors directive that accurately reflects the intended embedding policy. X-Frame-Options is either removed or retained only as a fallback for legacy browsers.

Do not

  • Do not rely on X-Frame-Options ALLOW-FROM; it is not supported by modern browsers.
  • Do not use both mechanisms without understanding that frame-ancestors takes precedence.
  • Do not assume that X-Frame-Options provides flexible origin control.
  • Do not set conflicting policies between X-Frame-Options and frame-ancestors.

How to verify

  • The Content-Security-Policy header includes a frame-ancestors directive.
  • The frame-ancestors directive matches the intended embedding policy.
  • X-Frame-Options is either removed or set to a compatible fallback.
  • The page embedding behavior is correct in modern browsers.

Find every page with this

probeo monitors this continuously across every page of your site, and records which pages passed, which failed, and which it could not determine.

Book a Call