How it works
In clickjacking, another site loads your page invisibly in a frame (an iframe) and lays something harmless on top, such as a “Claim your prize” button. Whoever clicks it is really clicking on your page: confirming an order, changing a setting or granting access without noticing. Because the visitor is logged in with you, the click counts.
The protection is that your page tells the browser who may embed it. There are two headers for that:
frame-ancestorsis a directive of the Content Security Policy.'self'allows only your own site,'none'nobody, and you can add individual addresses.X-Frame-Optionsis the older header with the valuesDENY(nobody) andSAMEORIGIN(only your own site).
If a browser knows frame-ancestors, it takes precedence over X-Frame-Options.
What matters
- At least one of the two. Without either, any site may embed your page.
- No wildcards in
frame-ancestors.*,https:orhttp:allow every site again. - No
ALLOW-FROM. Current browsers no longer know this value ofX-Frame-Optionsand ignore the whole header. If you want certain partners to embed your page, name them inframe-ancestors. - No conflicting values. If
X-Frame-Optionsappears more than once with different values, say once from the web server and once from the application, browsers ignore it. - Only as a header.
frame-ancestorshas no effect when the policy sits in a<meta>tag in the HTML.
How to set it up
The simple way:
X-Frame-Options: SAMEORIGIN
The modern way, as a policy of its own or as part of your existing one:
Content-Security-Policy: frame-ancestors 'self'
If partners should be allowed to embed your page, name them there: frame-ancestors 'self' https://partner.example. Both headers are set in the web server or the application, by you, your agency or through a header rule at your hosting provider or CDN. Many CMS security plugins have a switch for it.