Defaults.Exposed › Fixes › Clickjacking protection (X-Frame-Options)
How to fix Clickjacking protection (X-Frame-Options)
A one-line instruction that tells browsers not to let other websites secretly load your site inside their own. Without it, a scammer can hide your real, logged-in pages behind a fake page and trick your customers into clicking things they never meant to — approving a payment, changing a password, granting access.
Bottom line for your business: A fraudster can invisibly wrap your live website inside a fake one and steal money or account access from your logged-in customers — and to the customer it looks like your site did it. The fix is free and takes a developer about 15 minutes; leaving it off is a known gap that both criminals and cautious buyers can spot in seconds.
What this can cost you
- A scammer hides your real login or payment screen behind a harmless-looking page and tricks a customer into 'confirming' a transfer or a setting change without realising it — the customer blames you, not the attacker.
- Your logged-in account area gets loaded invisibly on top of a 'You've won — click to claim' page; the click actually approves a real change on the customer's account, and you field the angry support call.
- A prospect's IT team runs a quick security scan before signing, sees your site can be embedded by anyone, and flags it as a risk that stalls or kills the deal.
- Your brand becomes the bait in a fraud campaign; customers who get caught remember it as 'the company whose site let it happen.'
- An auditor or cyber-insurance scan lists missing clickjacking protection as a basic-hygiene failure — cheap to fix, embarrassing to have flagged.
Why it matters. This is a free, one-line setting that takes minutes to add, and it shuts down a whole class of trickery aimed at your logged-in customers. On our scoring it is a worth-real-points web-security check rated high severity, because a missing header leaves a known, easily-checked hole that criminals automate and buyers look for.
What this is, in plain words
When someone visits your website, their browser can also be told to load your site inside another website — like a small window embedded inside a bigger page. That sounds harmless, and sometimes it is. But it’s the mechanism behind an attack called clickjacking.
Here’s the trick. A scammer builds their own page and quietly loads your real website inside it — invisibly, made fully transparent. Then they lay their own content on top: a flashy button, a “Play video,” a “Claim your prize.” Your customer sees the attacker’s page and clicks what looks like a harmless button. But because your real site is sitting invisibly underneath their cursor, the click actually lands on your page — confirming a payment, changing a password, approving access, accepting a permission. The customer thinks they clicked one thing; they actually clicked another, on a site they trust.
Clickjacking protection is a short, invisible instruction your website sends to every visitor’s browser that says, in effect:
“Don’t let other websites load me inside them. If someone tries, refuse.”
Modern browsers obey this automatically. With it switched on, the trick simply doesn’t work — the embedded copy of your site refuses to load. Without it, your site is fair game to be used as the hidden layer in a scam, and the customer who gets caught will associate the whole thing with your brand, not the attacker’s.
What this can cost you
These are realistic, everyday scenarios. We never name a real business; these are illustrations of how the gap gets used.
-
The invisible “confirm.” A customer is logged into your account portal in one tab. They land on a page (from an ad, an email, a search result) that promises something tempting and shows a big “Continue” button. Hidden underneath that button is your real “Confirm transfer” or “Change email” control, loaded from their own logged-in session. They click “Continue” — and unknowingly authorise a change on their actual account with you. To them, and to your support team, it looks like they did it on your site.
-
The settings hijack. An attacker frames your account-settings page and overlays an innocent game or survey. A few clicks in the right places silently flip a setting — adding the attacker’s email as a recovery address, granting an app permission, or disabling a security alert. The account is now quietly compromised, and nothing looked wrong at the time.
-
The deal that stalls. A larger customer sends their standard security questionnaire before signing. One line asks whether your site sets anti-framing protection (X-Frame-Options / CSP frame-ancestors). Your IT contact has to answer “no,” and procurement pauses while you scramble to fix a free, 15-minute setting that now looks like a red flag in front of a buyer.
-
The brand-as-bait campaign. Because your real, trusted pages can be embedded, an attacker uses your login or checkout as the convincing layer in a wider phishing campaign. The customers who get caught don’t blame the shadowy attacker — they remember it as the time “your site” let them get scammed.
-
The audit flag. An insurer’s scan, or an auditor reviewing your security posture, lists missing clickjacking protection among the findings. It’s a textbook basic-hygiene item; having it flagged signals that the easy, free protections weren’t in place — which colours how the rest of your security is judged.
The through-line: the damage lands on a real, logged-in customer doing something they didn’t intend — and it carries your name, not the attacker’s.
What it actually is
When a browser asks your website for a page, your server sends back the page plus some invisible “headers” — extra instructions the browser reads but the visitor never sees. Clickjacking protection is delivered through these headers. There are two, and our check passes if either is present:
1. The older header — X-Frame-Options:
X-Frame-Options: SAMEORIGIN
This is the long-standing, widely-supported control. It takes one of two practical values:
SAMEORIGIN— your own site may embed its own pages, but no outside site can. The safe default for almost everyone.DENY— nobody may embed your pages, including you. Use this only if your site never frames its own content.
2. The modern header — Content-Security-Policy frame-ancestors:
Content-Security-Policy: frame-ancestors 'self';
This is the newer, more flexible control and the one current standards point to. It does the same job but lets you be precise about who may embed you:
frame-ancestors 'self'— equivalent toSAMEORIGIN.frame-ancestors 'none'— equivalent toDENY.frame-ancestors 'self' https://partner.example.com— your own site plus one named, trusted partner, and nobody else.
What “good” looks like
The strongest setup uses both: frame-ancestors for modern browsers (and for the precision of naming allowed embedders) and X-Frame-Options: SAMEORIGIN as a fallback for older clients. Our check is satisfied by either one on its own — but since both are free and take the same few minutes, there’s no reason not to set both.
One important detail your developer should know: a Content-Security-Policy-Report-Only header does not enforce anything — it only reports. If you want clickjacking protection to actually take effect, it must come from an enforcing header (a normal Content-Security-Policy with frame-ancestors, or X-Frame-Options), not a report-only one.
How to fix it (free, ~15 minutes)
Hand this section to whoever runs your website — your IT person, web developer, or hosting support. The fix is free. It’s one or two response headers, or a rule in your CDN. There is nothing to buy.
The check passes when either an X-Frame-Options header (set to DENY or SAMEORIGIN) or a CSP frame-ancestors directive is present. The recommended belt-and-braces setup adds both.
Step 1 — Decide how strict to be
- Most businesses:
SAMEORIGIN/frame-ancestors 'self'. Your own site keeps working; outsiders are blocked. - If your site never embeds its own pages:
DENY/frame-ancestors 'none'for maximum lockdown. - If a genuine partner must embed a specific page: name them explicitly with
frame-ancestors 'self' https://partner.example.com;and nobody else gets in.
Step 2 — Add the headers (pick your platform)
Nginx — inside your server block:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self';" always;
Apache — ensure mod_headers is enabled, then in your virtual host:
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "frame-ancestors 'self';"
Microsoft IIS — in web.config inside <customHeaders>:
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="Content-Security-Policy" value="frame-ancestors 'self';" />
Cloudflare (or a similar CDN): go to Rules → Transform Rules → Modify Response Header, and add two rules that set X-Frame-Options to SAMEORIGIN and Content-Security-Policy to frame-ancestors 'self'; on all responses. This is the easiest route if you don’t have direct server access.
Already sending a Content-Security-Policy for other reasons? Don’t create a second CSP header — add frame-ancestors into your existing policy. Two CSP headers can conflict.
Website builders (Squarespace, Wix, Shopify and similar): these platforms often set anti-framing protection for you, so you may already pass with nothing to do. If our check flags it, the control is usually in the platform’s security settings, or you add it at the CDN sitting in front of the site. (Note: Google Workspace and Microsoft 365 power your email, not your website — this header is set wherever your public site actually lives, not in Workspace/365 admin.)
Step 3 — Reload and verify
Reload the web server or deploy the CDN rule, then load your live site and check the response headers — browser dev tools → Network tab → click the page request → Response Headers, or any free header-checking tool. Confirm the header(s) appear on real page responses, not just the homepage. Then re-run the check.
Common mistakes
- Using a report-only CSP and assuming it protects you.
Content-Security-Policy-Report-Onlyonly reports violations — it enforces nothing. You need an enforcing header for the protection to take effect. - Setting two separate
Content-Security-Policyheaders. If you already have a CSP, addframe-ancestorsto it rather than emitting a second policy; conflicting CSP headers can produce unexpected behaviour. - Setting
DENYwhen your own site embeds its own pages.DENYblocks all framing, including your own. If any part of your site uses iframes of itself, useSAMEORIGIN/frame-ancestors 'self'instead, or you’ll break your own pages. - Only protecting the homepage. The pages that matter most for clickjacking are the logged-in ones — account settings, payment confirmation, admin. Make sure the headers are applied site-wide, not just to the front page.
- Assuming HTTPS or the padlock already covers this. Encryption and anti-framing are unrelated. A perfect certificate does nothing to stop your pages being embedded.
- Relying on old workarounds. “Frame-busting” JavaScript (scripts that try to break out of frames) is unreliable and can be bypassed. The headers are the correct, browser-enforced fix.
FAQ
I'm not technical — can I deal with this myself?
You don't need to do the technical part. It's a single setting added to your website's server or your CDN, and any web developer or IT provider can add it in a few minutes. Hand them the 'How to fix it' section below — it tells them exactly what to add. The fix is free; we only charge if you'd like us to keep monitoring that it stays in place.
Will this stop my own site, or legitimate partners, from displaying my pages?
Only if you set it too strictly. The common setting ('SAMEORIGIN', or 'frame-ancestors self') still lets your own website embed its own pages normally — it only blocks outside sites. If a genuine partner needs to embed one specific page of yours, your developer can allow that single source while still blocking everyone else.
We're a small business — would anyone really bother targeting us?
These attacks are run in bulk by automated tools, not hand-picked. Smaller sites are often hit precisely because they're the ones missing basic protections like this. The attacker doesn't need to know who you are — they just need your site to be embeddable. Closing the gap costs you nothing.
What does 'good' actually look like?
Either an X-Frame-Options header set to SAMEORIGIN (or DENY), or a Content-Security-Policy with a frame-ancestors directive — ideally both. Our check passes if either one is present. The modern, more flexible control is frame-ancestors; X-Frame-Options is the older header that still covers some legacy browsers, so the belt-and-braces setup uses both.
Isn't this the same as the SSL padlock or HTTPS?
No — they protect against completely different things. HTTPS encrypts the connection so nobody can read it in transit. Clickjacking protection stops your pages being loaded inside someone else's site at all. You can have a perfect padlock and still be wide open to clickjacking. They're separate checks and you want both.
If we don't fix it, does it lower our grade?
Yes. This is a scored web-security check, not informational — a missing header costs points and is rated high severity, because it directly exposes your logged-in customers to fraud. It's also one of the cheapest points to recover: a single free header, about 15 minutes of a developer's time.