Security Header Guide
Master the Content Security Policy frame-ancestors directive for modern clickjacking protection
The Content Security Policy (CSP) frame-ancestors directive is the modern, flexible replacement for the X-Frame-Options header. It provides granular control over which websites are allowed to embed your content in iframes, frames, or objects.
Unlike X-Frame-Options, CSP frame-ancestors offers more sophisticated control mechanisms, including the ability to specify multiple allowed domains, use wildcards, and combine with other CSP directives for comprehensive security policies.
CSP frame-ancestors provides the flexibility needed for modern web applications while maintaining strong security. It is the recommended approach for new applications and offers future-proof protection against clickjacking attacks.
Prevents your site from being displayed in any iframe. Equivalent to X-Frame-Options: DENY.
Content-Security-Policy: frame-ancestors 'none';Allows your site to be framed only by pages from the same origin.
Content-Security-Policy: frame-ancestors 'self';Allows your site to be framed only by specific, trusted domains.
Content-Security-Policy: frame-ancestors 'self' https://trusted.com;Use wildcards to allow framing by multiple domains matching patterns.
Content-Security-Policy: frame-ancestors *.example.com;Configure CSP frame-ancestors in Apache:
# In httpd.conf or .htaccess file Header always set Content-Security-Policy "frame-ancestors 'none';" # 'self' configuration Header always set Content-Security-Policy "frame-ancestors 'self';" # Specific domains Header always set Content-Security-Policy "frame-ancestors 'self' https://trusted.com;" # Multiple domains with wildcards Header always set Content-Security-Policy "frame-ancestors 'self' https://*.partner.com;" # Combined with other CSP directives Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; frame-ancestors 'none';"
Set CSP frame-ancestors in Nginx:
# In nginx.conf or site configuration
add_header Content-Security-Policy "frame-ancestors 'none';" always;
# 'self' configuration
add_header Content-Security-Policy "frame-ancestors 'self';" always;
# Specific domains
add_header Content-Security-Policy "frame-ancestors 'self' https://trusted.com;" always;
# Full CSP policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; frame-ancestors 'none';" always;
# Location-specific configuration
location /admin/ {
add_header Content-Security-Policy "frame-ancestors 'none';" always;
}Use helmet middleware for Express.js:
const express = require('express');
const helmet = require('helmet');
const app = express();
// Basic CSP configuration
app.use(helmet({
contentSecurityPolicy: {
directives: {
frameAncestors: ["'none'"],
},
},
}));
// 'self' configuration
app.use(helmet({
contentSecurityPolicy: {
directives: {
frameAncestors: ["'self'"],
},
},
}));
// Specific domains
app.use(helmet({
contentSecurityPolicy: {
directives: {
frameAncestors: ["'self'", "https://trusted.com"],
},
},
}));Set CSP headers in PHP applications:
<?php
// Basic CSP header
header("Content-Security-Policy: frame-ancestors 'none';");
// 'self' configuration
header("Content-Security-Policy: frame-ancestors 'self';");
// Specific domains
header("Content-Security-Policy: frame-ancestors 'self' https://trusted.com;");
// WordPress functions.php
add_action('send_headers', function() {
header('Content-Security-Policy: frame-ancestors 'none';');
});
// Laravel middleware
class CSPFrameAncestorsMiddleware
{
public function handle($request, Closure $next, $policy = "'none'")
{
$response = $next($request);
$response->header('Content-Security-Policy', "frame-ancestors $policy;");
return $response;
}
}X-Frame-Options: DENY→frame-ancestors 'none'X-Frame-Options: SAMEORIGIN→frame-ancestors 'self'For maximum compatibility during transition, implement both headers:
X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none';
Verify your Content-Security-Policy frame-ancestors header is properly configured.