CSP frame-ancestors vs X-Frame-Options

Sunday, February 25, 2024
3 min read
Theotime QuereTheotime Quere
Protecting against clickjacking attacks is crucial for web security. Both X-Frame-Options header and CSP's frame-ancestors directive provide mechanisms to control how your website can be embedded in frames, iframes, or objects.

Understanding X-Frame-Options

X-Frame-Options is an HTTP response header that allows you to control whether a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object>. This helps avoid clickjacking attacks.

Available Values

  • DENY: Prevents any domain from framing the content
  • SAMEORIGIN: Allows framing only by pages on the same origin
  • ALLOW-FROM origin (Deprecated): Allowed framing by specific domains (no longer supported by modern browsers)

Example of X-Frame-Options header

X-Frame-Options "DENY";

Implementation in different web servers:

Nginx

Add to your server block:

Example of X-Frame-Options header on Nginx

add_header X-Frame-Options "DENY";

Apache

Add to your .htaccess or configuration:

Example of X-Frame-Options header on Apache

Header set X-Frame-Options "DENY"

Next.js

Add to your next.config.js:

Example of X-Frame-Options header in Next.js

module.exports = {
async headers() {
  return [
    {
      source: '/:path*',
      headers: [
        {
          key: 'X-Frame-Options',
          value: 'DENY'
        }
      ]
    }
  ]
}
}

CSP frame-ancestors Directive

The frame-ancestors directive is part of Content Security Policy and provides more granular control over who can embed your content. Learn more about Content Security Policy

Directive Values

  • 'none': Prevents any embedding
  • 'self': Allows embedding only from the same origin
  • URI/Domain: Allows embedding from specific sources

Example of frame-ancestors directive

Content-Security-Policy: frame-ancestors 'self' https://trusted.com;

Meta Tag Limitation

The frame-ancestors directive is not supported in meta tags. It must be set via HTTP header.

Learn about CSP meta tags limitations

Header Priority in Modern Browsers

When both X-Frame-Options and frame-ancestors are present, modern browsers will prioritize the frame-ancestors directive and ignore X-Frame-Options completely.

Example of conflicting header policies

X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors https://allowed-domain.com;

Browser Behavior

In this example, modern browsers will allow framing from allowed-domain.com, completely ignoring the DENY from X-Frame-Options.

• Modern Browsers :

Will only enforce frame-ancestors when present, ignoring X-Frame-Options

• Legacy Browsers

Will fall back to X-Frame-Options if frame-ancestors is not supported

Important Note

Due to this priority behavior, ensure your frame-ancestors directive is at least as restrictive as your X-Frame-Options header to maintain security across all browsers.

Comparing Both Approaches

  • X-Frame-Options

    Simple to implement but limited in functionality

    • Only supports one domain with ALLOW-FROM (deprecated)
    • Limited browser support for some features
  • frame-ancestors

    More flexible and powerful, with better browser support

    • Supports multiple domains
    • Widely supported in modern browsers
    • Provides more granular control

Best Practices

Implementation Guidelines

Follow these best practices to ensure maximum security and compatibility across browsers.

  • Use both headers for maximum compatibility
  • Prefer frame-ancestors for modern browsers
  • Use DENY by default unless embedding is required
  • Regularly audit allowed domains
Check your configuration with our CSP scanner

Example of using both headers for maximum protection & compatibility

Content-Security-Policy: frame-ancestors 'none';
X-Frame-Options: DENY

Recommendation

While using both headers provides the best coverage, frame-ancestors is the modern standard and should be your primary method of control.

Common Use Cases

  • Public Content : Use 'none' to prevent any framing
  • Internal Tools : Use 'self' to allow same-origin framing
  • Partner Integration : Specify allowed partner domains

Conclusion

While X-Frame-Options provides basic protection against clickjacking, the CSP frame-ancestors directive offers more flexibility and better browser support. Using both headers ensures maximum compatibility across browsers while providing robust protection against framing-based attacks.