Prevent Clickjacking with frame-ancestors

Use the CSP frame-ancestors directive to prevent clickjacking attacks. Understand how it replaces X-Frame-Options with more flexible origin control and iframe embedding policies.

Security Best Practices

Detailed Explanation

Preventing Clickjacking with frame-ancestors

Clickjacking is an attack where a malicious site embeds your page in an invisible <iframe> and tricks users into clicking on it. The frame-ancestors directive controls which origins can embed your page, effectively replacing the older X-Frame-Options header.

Basic Usage

Content-Security-Policy: frame-ancestors 'none'

This prevents your page from being embedded in any iframe, object, or embed element — equivalent to X-Frame-Options: DENY.

Common Configurations

Block all framing (most secure):

frame-ancestors 'none'

Allow same-origin framing only:

frame-ancestors 'self'

Equivalent to X-Frame-Options: SAMEORIGIN.

Allow specific origins:

frame-ancestors 'self' https://partner.example.com https://dashboard.example.com

This allows your page to be embedded by the specified origins — something X-Frame-Options could not do (it only supported DENY and SAMEORIGIN).

Allow any HTTPS origin:

frame-ancestors https:

frame-ancestors vs X-Frame-Options

Feature frame-ancestors X-Frame-Options
Multiple origins Yes No
Wildcard subdomains Yes (*.example.com) No
CSP integration Yes Separate header
Browser support Modern browsers All browsers
Deprecated No Effectively yes

Recommendation: Use both headers for maximum compatibility:

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

Important: frame-ancestors Does Not Fall Back to default-src

Unlike most directives, frame-ancestors is not governed by default-src. You must set it explicitly:

# This does NOT protect against clickjacking:
Content-Security-Policy: default-src 'none'

# You must explicitly add:
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'

Widget and Embed Use Cases

Some applications are designed to be embedded (chatbots, payment forms, embedded calendars). For these:

# Allow embedding by customer domains
frame-ancestors https://customer1.com https://customer2.com

# Allow embedding by any subdomain of a platform
frame-ancestors https://*.shopify.com

Double Framing Protection

frame-ancestors protects against nested framing (double framing attacks). The browser checks the frame-ancestors policy against every ancestor in the frame hierarchy, not just the immediate parent.

Meta Tag Limitation

Critical: frame-ancestors cannot be set via a <meta> tag. It must be delivered as an HTTP response header. This is intentional — if it could be set in HTML, an attacker who can inject HTML could remove the protection.

Use Case

Every web application should set frame-ancestors to prevent clickjacking. Banking and financial applications use frame-ancestors 'none' for maximum protection. SaaS platforms that offer embeddable widgets use frame-ancestors with specific customer domains. E-commerce checkout pages use frame-ancestors 'self' to prevent their payment forms from being framed by phishing sites.

Try It — CSP Header Generator

Open full tool