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.
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.