Clickjacking is one of those attacks that sounds simple but causes real damage. The attacker embeds your site in an invisible iframe on their malicious page. They overlay deceptive content on top of the invisible iframe. When the visitor clicks what they think is a button on the malicious page, they are actually clicking something on your site.
The visitor did not authorize the action. They did not even realize they were on your site. But the action happens anyway because their browser is logged in.
X-Frame-Options is the security header that prevents this. The configuration is simple. The protection is real. The header should be on every site that does anything users would not want done without their knowledge.
This piece covers what clickjacking actually is, how X-Frame-Options prevents it, how to configure it, and when to use alternatives.
What Clickjacking Is
The attack uses standard web features in unexpected ways.
The Basic Mechanism
The attacker creates a malicious page. The page contains an iframe that loads your site. The iframe is hidden through CSS (zero opacity, off-screen positioning, or covered by other content).
The malicious page shows attractive content where the user expects to click. A “Click here to win” button. A game. Anything that gets users to click.
When the user clicks, the click actually goes through to the hidden iframe loading your site. The action that gets triggered is whatever is at that position on your site.
What Makes This Work
Browsers send cookies with iframe requests just like with main requests. If the user is logged into your site, the iframe loads their authenticated version of your site.
When the user clicks (thinking they are clicking on the attacker’s content), the click goes to the authenticated session on your site.
Anything the user could do logged in, the attacker can trick them into doing through clickjacking.
Real-World Examples
Clickjacking has been used for various attacks over the years:
Tricking users into “liking” Facebook pages they would not normally like.
Causing users to follow accounts on Twitter without realizing.
Triggering money transfers on banking sites.
Granting permissions to applications that should not have access.
Making purchases on e-commerce sites.
The targets are anywhere a single click can perform an action.
Why Users Cannot Easily Detect Clickjacking
The attack is invisible from the user’s perspective. The malicious page looks normal. The click feels normal. The action happens silently on your site.
The user has no idea anything happened on your site until they notice the consequences later.
How X-Frame-Options Stops Clickjacking
The defense is straightforward.
The Browser Refuses to Frame
X-Frame-Options is a HTTP response header. When the browser sees it on a page, the browser refuses to display the page in an iframe (depending on the value).
The attacker’s iframe cannot load your site. Without the iframe, there is nothing to clickjack. The attack fails.
The Three Possible Values
X-Frame-Options accepts three values:
DENY refuses framing entirely. The page cannot be displayed in any iframe on any site.
SAMEORIGIN allows framing only from the same domain. Your site can frame its own pages, but other sites cannot frame your pages.
ALLOW-FROM is older and allows framing from a specific origin. This value is deprecated and not supported by modern browsers. Use Content-Security-Policy frame-ancestors instead.
Choosing Between DENY & SAMEORIGIN
For most sites, SAMEORIGIN is the right choice. It blocks external framing while allowing your site to frame its own pages.
DENY is more restrictive. Use it if your site never needs to be framed by anything, including itself.
If your site needs to be frameable by specific other sites (partner integrations, embed features), you need a different approach. The next section covers this.
How to Set X-Frame-Options
The implementation depends on your platform.
Apache
Add to .htaccess or virtual host configuration:
Header set X-Frame-Options “SAMEORIGIN”
Nginx
Add to server configuration:
add_header X-Frame-Options “SAMEORIGIN” always;
WordPress
Most security plugins set X-Frame-Options. iThemes Security, Wordfence, Sucuri all include this option.
For finer control, custom code can add the header through functions.php or a custom plugin.
Cloudflare
Cloudflare lets you set custom headers through its dashboard or Transform Rules.
IIS
For Windows IIS servers, add through web.config:
<httpProtocol> <customHeaders> <add name=”X-Frame-Options” value=”SAMEORIGIN” /> </customHeaders> </httpProtocol>
When You Need More Flexibility
X-Frame-Options is binary. It either blocks all external framing or allows it. For more complex needs, use Content-Security-Policy.
Frame-Ancestors Directive
The CSP frame-ancestors directive controls iframe embedding with more flexibility than X-Frame-Options.
Content-Security-Policy: frame-ancestors ‘self’ https://trusted-partner.com;
This allows your site to be framed by itself and by trusted-partner.com. Other sites still cannot frame your pages.
Multiple Allowed Origins
You can list multiple allowed origins:
Content-Security-Policy: frame-ancestors ‘self’ https://partner1.com https://partner2.com;
Wildcard Support
CSP supports wildcards in domain names:
Content-Security-Policy: frame-ancestors ‘self’ https://*.partner.com;
This allows framing from any subdomain of partner.com.
Combining With X-Frame-Options
You can set both headers. Modern browsers prioritize frame-ancestors when both are present. Older browsers fall back to X-Frame-Options.
For maximum compatibility, set both:
X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors ‘self’;
Testing Clickjacking Protection
After setting the header, verify it works.
Manual Testing
Create a test HTML page with an iframe pointing at your site:
<iframe src=”https://yoursite.com”></iframe>
Open this page in a browser. The iframe should show an error or be blank instead of loading your site.
If the iframe loads, the protection is not working. Investigate the configuration.
Browser Developer Tools
Look at the response headers for your pages. The Network tab shows all headers. X-Frame-Options or Content-Security-Policy frame-ancestors should be present.
Online Tools
Security Headers (securityheaders.com) checks for X-Frame-Options as part of its scan.
Browser Console Messages
When the browser blocks an iframe due to X-Frame-Options, it usually logs a message to the console. This message confirms the header is working.
When Sites Legitimately Need to Be Framed
Some sites need to be embedded in iframes by design.
Embedded Players
Video and music services need to be embeddable so users can include the player on their sites. YouTube, Vimeo, SoundCloud all need framing.
For these, X-Frame-Options should not be too restrictive.
Widgets & Tools
Calculators, calendars, booking widgets, and other tools designed to be embedded need to be frameable.
Documentation Embeds
Some documentation platforms allow embedding pages in other sites. The pages need to be frameable.
Approach for These Cases
Set framing controls based on actual needs. Embedded services might use:
X-Frame-Options: SAMEORIGIN for sensitive pages.
No X-Frame-Options for content meant to be embedded.
Frame-ancestors with specific origins for partner integrations.
The decision is page by page, not site by site.
Common Clickjacking Defense Mistakes
People stumble in predictable ways.
Not Setting the Header at All
The most common mistake. Sites without X-Frame-Options can be framed and clickjacked.
The cost of setting the header is minimal. The protection is real.
Setting It Too Restrictively
DENY breaks legitimate embedding cases. If your site has features that need to be embedded, DENY is wrong.
Not Testing After Setup
Sometimes the header gets added incorrectly or gets overridden somewhere. Always test after configuration.
Forgetting About Specific Pages
Pages that perform sensitive actions need protection. Pages that need to be embedded might not. Per-page configuration sometimes makes sense.
Using Only X-Frame-Options Without CSP
Modern security recommends both X-Frame-Options (for older browser compatibility) and CSP frame-ancestors (for modern browser support and finer control).
Trusting Origin Headers Too Much
Some attackers can manipulate origin headers in specific scenarios. The browser-side enforcement of X-Frame-Options is more reliable than server-side origin checking.
What Clickjacking Cannot Be Used For
Understanding the limits helps too.
Reading Data
Clickjacking causes actions but does not read data from your site. The attacker triggers clicks but cannot see what your site shows.
This makes clickjacking less useful than attacks like XSS for data theft.
Actions Requiring User Input
Clickjacking can trigger clicks but cannot fill in forms or provide input. Actions that require user input beyond clicking cannot be fully clickjacked.
This is why many sensitive actions require confirmation steps that involve typing or entering codes.
Multi-Step Actions
Clickjacking is most effective for single-click actions. Multi-step processes where each step requires deliberate action are harder to clickjack.
For high-risk actions, requiring multiple steps adds protection beyond X-Frame-Options.
Closing Thoughts on Frame Defense
Clickjacking is one of the easier attacks to defend against. X-Frame-Options is one of the easier security headers to configure. The combination provides good protection against this category of attack.
For most sites, the right approach is straightforward. Set X-Frame-Options to SAMEORIGIN. Add Content-Security-Policy frame-ancestors for additional coverage and finer control. Test that the headers are working. Done.
Sites that get clickjacked typically have no framing protection at all. The protection is straightforward enough that not having it is a sign of inattention to basic security rather than a deliberate choice.
For sites with legitimate framing needs (video players, embedded widgets, partner integrations), the configuration needs more thought. Specific origins can be whitelisted. Specific pages can have different policies. The flexibility exists when needed.
If your site has not been configured for clickjacking protection, this is one of the easier security improvements available. The work is bounded. The protection is real. The implementation is usually a few lines of server configuration or a plugin setting.
Sites that take security seriously have clickjacking protection as part of the baseline configuration. The absence of protection means accepting the risk of clickjacking attacks, which is rarely the right trade-off when the protection is so easy to add. Make X-Frame-Options part of your standard site setup, and one more category of attack becomes something you do not have to worry about.