Skip to content

Security Headers

X-Frame-Options and clickjacking — how to stop your site being framed

What clickjacking is, how X-Frame-Options and CSP frame-ancestors stop it, and copy-paste examples for nginx, Apache and Netlify.

By SurfaceWatch··4 min read

Imagine a harmless-looking page with a big "Play video" button. Behind that button, invisible, sits your site's "Delete account" or "Confirm payment" button, loaded in a transparent frame. The visitor thinks they are clicking play. They are clicking yours. That attack is called clickjacking, and it only works if other sites are allowed to put your pages inside a frame.

The fix is one response header that tells the browser who may frame your site.

The two headers that do it

X-Frame-Options is the older header, supported everywhere:

X-Frame-Options: DENY
  • DENY: nobody may frame this page, not even your own site.
  • SAMEORIGIN: only pages on your own domain may frame it.

Content-Security-Policy: frame-ancestors is the modern replacement, and more flexible:

Content-Security-Policy: frame-ancestors 'none'
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com

Where both are present, browsers that understand frame-ancestors follow it and ignore X-Frame-Options. Sending both is fine and covers old browsers too. If you already have a CSP (see our CSP guide), add frame-ancestors to it.

Which value should you pick?

  • If nobody should embed your site, use DENY / frame-ancestors 'none'. This is right for most sites.
  • If you frame your own pages (a preview panel, an admin widget), use SAMEORIGIN / frame-ancestors 'self'.
  • If a partner must embed you, list their exact origin in frame-ancestors. X-Frame-Options can't express that cleanly.

Copy-paste examples

nginx

add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none'" always;

Apache

Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"

Netlify (_headers file)

/*
  X-Frame-Options: DENY
  Content-Security-Policy: frame-ancestors 'none'

How to check your site

Run curl -sI https://yourdomain.com | grep -iE "x-frame|frame-ancestors". If you see nothing, your pages can be framed by anyone. SurfaceWatch checks your security headers in one click, flags this one when it's missing, and gives you the exact lines to paste for your platform.

Clickjacking protection is one of the cheapest fixes there is: one header, no code changes, and it closes a whole class of attacks. Add it today.

Keep reading

Check your site's headers — add SurfaceWatch free

One click, an honest grade, and the exact fix. Free to install. No account needed.