How to Prevent Clickjacking
Clickjacking tricks users into clicking hidden elements by overlaying your site in an invisible iframe on a malicious page. The attacker can make users perform actions without their knowledge. This guide covers how to prevent your site from being framed.
Find security issues automatically before attackers do.
Follow These Steps
Add X-Frame-Options header
This header prevents your site from being loaded in iframes.
// X-Frame-Options: DENY (recommended - blocks all framing)
// X-Frame-Options: SAMEORIGIN (allows framing by your own domain)
// In next.config.js
{ key: 'X-Frame-Options', value: 'DENY' }Add CSP frame-ancestors directive
CSP frame-ancestors is the modern replacement for X-Frame-Options with more control.
// Block all framing
Content-Security-Policy: frame-ancestors 'none'
// Allow framing by same origin
Content-Security-Policy: frame-ancestors 'self'
// Allow specific domains to frame your site
Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.comUse both headers for compatibility
Include both X-Frame-Options and CSP frame-ancestors for maximum browser support.
// next.config.js
module.exports = {
async headers() {
return [{
source: '/(.*)',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'none'" }
]
}]
}
}Test your clickjacking protection
Verify that your site cannot be loaded in an iframe.
<!-- Create a test HTML file -->
<html>
<body>
<h1>Clickjacking Test</h1>
<iframe src="https://yourdomain.com" width="500" height="500"></iframe>
<!-- This iframe should show an error or be blank -->
</body>
</html>Open this test file locally and verify the iframe does not load your site.
Handle exceptions for embedded content
If specific pages need to be embeddable, create targeted exceptions.
// In next.config.js - different headers for different paths
module.exports = {
async headers() {
return [
{
source: '/embed/:path*',
headers: [
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'self' https://trusted-site.com" }
]
},
{
source: '/((?!embed).*)',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'none'" }
]
}
]
}
}What You'll Achieve
Your application is protected against clickjacking with both X-Frame-Options and CSP frame-ancestors headers. Embeddable content has targeted exceptions while all other pages block framing.
Common Mistakes to Avoid
Mistake
Only using X-Frame-Options without CSP
Fix
X-Frame-Options is older and less flexible. Use both for compatibility and add CSP frame-ancestors for modern browsers.
Mistake
Setting SAMEORIGIN when DENY is needed
Fix
If your site never needs to be framed, use DENY. SAMEORIGIN is only needed if your own pages use iframes to embed other pages from your domain.
Frequently Asked Questions
Do I need both X-Frame-Options and CSP frame-ancestors?
For maximum compatibility, yes. Older browsers only support X-Frame-Options. Modern browsers prefer CSP frame-ancestors. Include both.
What if my site needs to be embedded in iframes?
Use CSP frame-ancestors to allow specific trusted domains. Use path-specific headers to only allow framing on pages designed for embedding.
Ready to Secure Your App?
VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.
Start Security Scan