Combating ClickJacking With X-Frame-Options

Back in January of 2009, I announced IE8’s support for a new header-specified directive: X-Frame-Options, that can be used to mitigate ClickJacking attacks. As a declarative security measure, X-Frame-Options has minimal compatibility impact, but requires adoption by clients and servers in order to provide its security benefit.

Since its introduction in IE8, we’ve seen a number of sites and other browsers adopt support for this directive as a mechanism to prevent malicious framing of content (called “ClickJacking” or “UI Redress” attacks), since frame-busting scripts can be defeated.

Browser Support

You can determine if your browser supports the X-Frame-Options directive using this test page. When permission to frame is denied, some browsers (e.g. IE, Opera) will show a message that allows the user to safely open the target page in a new window. Other implementations (e.g. Chrome, Firefox, Safari) will simply render an empty frame.

Browsers Supporting X-Frame-Options


In October 2013, informational RFC7034 was published which defines the X-Frame-Options header and its values.

Using X-Frame-Options in Web Applications

Web developers can send a HTTP header named X-FRAME-OPTIONS on HTML responses to restrict how the page may be framed. Note that this token must be sent as a HTTP Header, and the directive will be ignored if found in a META HTTP-EQUIV tag.

Token Values

The X-Frame-Options header may contain one of three tokens:

  • DENY
  • ALLOW-FROM origin 

If the X-FRAME-OPTIONS value contains the token DENY, browsers will prevent the page from rendering if it will be contained within a frame. For instance, if contains a DENY directive, that page will not render in a subframe, no matter where the parent frame is located.

If the value contains the token SAMEORIGIN, the browser will block rendering only if the origin of the top-level browsing-context is different than the origin of the content containing the X-FRAME-OPTIONS directive.  For instance, if contains the X-FRAME-OPTIONS directive with the SAMEORIGIN token, the page may be framed by any page from the exact origin.

If the value contains the token ALLOW-FROM origin, the browser will block rendering only if the origin of the top-level browsing context is different than the origin value supplied with the Allow-From directive. For instance, if contains the X-FRAME-OPTIONS directive with the value Allow-From, then the page may be framed only by pages from the origin.

Note that the Allow-From token does not support wildcards or listing of multiple origins. For cases where the server wishes to allow more than one page to frame its content, the following design pattern is recommended:

  1. The outer IFRAME supplies its own origin information, using a querystring parameter on the Inner IFRAME's src attribute; e.g. http://sitetoframe/pagetoframe.asp? That querystring value can obviously be specified by an attacker, but that's fine.
  2. The server for the inner IFRAME verifies the supplied FromOrigin information meets whatever criteria business practices call for. For example, the server that serves the IFRAME containing a social network's "Like" button, might check to see that the supplied FromOrigin matches the FromOrigin expected for that Like button, and that the owner of the specified FromOrigin has a valid affiliate relationship, etc.
  3. If satisfied with the information supplied, the server for the Inner IFRAME sends an X-FRAME-OPTIONS: allow-from header
  4. The Browser then enforces the X-FRAME-OPTIONS directive.

If an attacker had specified a bogus origin in step #1 (different than the actual origin of the outermost page), he'd be blocked at step #4 when the browser actually enforces the Allow-From restriction.

There's a test page for these tokens here:

Best Practices


As outlined in point #2, you must ensure that you send the X-Frame-Options directive for the pages that need it. This typically includes checkout or bank-transfer confirmation pages, pages that contain one-click purchase links, or pages that make permanent configuration changes. While you could send an X-Frame-Options directive for all of your site’s pages, this has the potential downside that it forbids even non-malicious framing of your content (for instance, when the user visits your site using a Google Image Search results page).

Point #3 requires some explanation-- The question of when to use DENY and when to use SAMEORIGIN is an interesting one. It comes down to the expected use case for the page protected with the directive. If you never expect the page to be framed, you should use DENY. If you expect the page to be framed only by pages on your server (e.g. it's part of a FRAMESET) then you'll want to use SAMEORIGIN.

Keep in mind that if a page specifies SAMEORIGIN, browsers will forbid framing only if the top-level origin FQDN (fully-qualified-domain-name, aka what you see in the address bar) does not exactly match FQDN of the subframe page that demanded the SAMEORIGIN restriction. Your critical pages should specify DENY if your site has a page that permits hosting of arbitrary frames. For instance, suppose your site has a page like:, where your page embeds a frame pointed at the URL specified in the query string.

If you were to specify the SAMEORIGIN directive on your response, it would be vulnerable to ClickJacking by The top-level page ( and the grandchild frame ( would share the same origin, and thus the frame between top-level and the grandchild can ClickJack that grandchild.

Thanks for reading, and thanks to the other browsers for supporting this mechanism!


Comments (12)

  1. Sephiroth says:

    Firefox 3.6.9 will support X-Frame-Options too!


  2. EricLaw [MSFT] says:

    @raul: That does not appear to be a question. The "Test page" link in this post allows you to see if your browser supports this header.…/ie8-security-part-vii-clickjacking-defenses.aspx explains how ClickJacking works and shows a simple attack.

  3. Marc says:

    If you specify SAMEORIGIN, IE chokes on a HTTP page including a HTTPS frame on the same server. This is not logical – especially in this direction.

  4. EricLaw [MSFT] says:

    @Marc: If by "chokes" you mean "blocks", then yes, this is by-design. Please go read up on the definition of Origin. Thanks!

  5. Yay! Firefox 18 now supports the Allow-From directive in X-Frame-Options anti-clickjacking header.…/Firefox_18_for_developers

  6. Carl says:

    I'm missing a same-domain value option so embedding of frames could be generally allowed inside a company's domain e.g. * without looking to the hostname. If a company has multiple portals shared on different hosts it may get cumbersome to achieve the right maaping between applications and embedding hosts…

    EricLaw: The expectation in this scenario is that your code will use the Allow-From syntax to explicitly permit the domains of your choice.

  7. Ravindra Mahato says:

    Questions: Consider my site is hosted as, and can i use multiple X-frame-Options AllowFrom as below

    As u specified a design pattern for using ALLOWFROM option for multiple domain . can you give us an Example.

    [EricLaw] AllowFrom allows exactly ONE origin. If you want to support multiple sites, your design pattern should be that the hosting page supplies its origin in the request to your site. For instance <iframe src=>.

    Your site looks at the HostedBy parameter. If your site trusts to host you, then  and echo out ALLOWFROM FOO.COM. (A bad guy cannot "lie" with a bogus origin that isn't his because the browser itself will enforce that the outerpage matches the ALLOWFROM directive.)

  8. ke Lee says:

    I used <meta http-equiv="X-Frame-Option" content="deny"/> but it doesn't work.

    [EricLaw] As stated in the post: "the directive will be ignored if found in a META HTTP-EQUIV tag." You must send this directive as a HTTP header.


    1. Reinier says:

      Does IE support a port to the URL for X-Frame-Options? example:

      X-Frame-Options: ALLOW-FROM

  9. Michael says:

    how can I add multiple ALLOW-FROM origin URLs in an IIS??

  10. Hi, I am trying to allow multiple domains for click jacking by using the below header but this doesn’t seems to be working on IE and firefox. This is working fine at google chrome. Please can you suggest anything on this.
    add_header X-Frame-Options “ALLOW-FROM *,*,*

    1. You can only specify one domain using this attribute (which isn’t supported in Chrome). Use CSP’s Frame-Ancestors instead.

Skip to main content