How to fix a missing X-Frame-Options header (clickjacking protection)
Your site is missing X-Frame-Options (or CSP frame-ancestors), which means any other site can embed yours in an iframe. Attackers use this for clickjacking — overlaying an invisible copy of your site on a decoy page so users unknowingly click buttons on your app. Fix it with one of two headers: `X-Frame-Options: DENY` (blocks all iframe embedding) or the modern equivalent `Content-Security-Policy: frame-ancestors 'none'`. If you need to allow embedding on specific domains, use `frame-ancestors` with a list.
Why it matters
Clickjacking is especially dangerous for apps with one-click destructive actions — subscribe, pay, share, delete. An attacker can make users perform these without realizing. Browsers no longer display a warning when a site is framed.
How to check
- 01Check the Response Headers for `x-frame-options` or `content-security-policy` with `frame-ancestors`.
- 02Try embedding your site: create an HTML file with `<iframe src="https://your-site.com"></iframe>` and open it in a browser.
- 03If the iframe renders your page, you are vulnerable.
Or let SafeToShip check it for you in 60 seconds:
How to fix it
Next.js
Add both headers for belt-and-suspenders protection.
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'none'" }
]Generic
Send both headers on every HTML response.
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'AI prompt
Copy-paste into your AI tool
Paste this prompt into Cursor, Lovable, Bolt, v0, or Claude Code and it will walk through the fix for your specific codebase.
Add X-Frame-Options: DENY to my app, plus a Content-Security-Policy header with frame-ancestors 'none'. If I already have a CSP header, merge the frame-ancestors directive into it. Apply to all routes.FAQ
Frequently asked questions
- What if I want to embed my own app in a subdomain?
- Use `frame-ancestors 'self'` or list specific domains: `frame-ancestors 'self' https://app.example.com`. `DENY` blocks all embedding, including from your own site.
- Is X-Frame-Options deprecated?
- Modern browsers prefer CSP `frame-ancestors`, but X-Frame-Options still works and some older browsers only respect that one. Ship both; they do not conflict.
- Do SameSite cookies replace this?
- No. SameSite protects against CSRF by blocking third-party cookie use. Clickjacking does not need cookies — the attacker tricks the user into clicking while logged in normally. You need both.
Related fix guides
Fix these too
Missing CSP header
A missing Content-Security-Policy header lets attackers inject scripts into your site. Here is what CSP does, why you need it, and how to add it in Next.js, Vercel, and Supabase apps.
Read moreCookie missing SameSite
SameSite controls whether cookies are sent on cross-site requests — the main defense against CSRF. Here is how to set it.
Read moreLearn the concepts
Glossary
X-Frame-Options
A response header that stops other sites from embedding your page in an iframe, preventing clickjacking attacks.
Read moreContent Security Policy
CSP is a browser feature that tells your site which scripts, styles, and images are allowed to run. It is the main defense against cross-site scripting (XSS).
Read moreCross-Site Request Forgery
CSRF tricks a logged-in user into performing actions on your site without realizing. SameSite cookies are the modern defense.
Read moreFree tools
Check this yourself
Platform guides
Building on these platforms?
Next.js security
Next.js is the most popular React framework, but even experienced developers miss security headers and accidentally expose server files in production.
Read moreVercel security
Vercel handles hosting and SSL, but your application code still needs security hardening. Missing CSP headers and exposed environment variables are the top issues.
Read moreLovable security
Lovable makes it easy to ship fast, but AI-generated backends often ship with open Supabase tables and leaked API keys. Scan your Lovable app before your users find out.
Read moreScan your site for this and 50+ other issues
Free scan. Results in 60 seconds. No account required.