Change record status: 
Project: 
Introduced in branch: 
7.x
Introduced in version: 
7.50
Description: 

As of Drupal 7.50, Drupal core now protects against clickjacking by default by emitting the 'X-Frame-Options: SAMEORIGIN' header. This prevents the site from being embedded in an iframe on another domain.

This should not be disruptive for contributed modules or existing sites, unless a contributed module or site wants to embed the Drupal site somewhere else (e.g. for example in a Facebook application). In the case where you do need to override this behavior, methods for doing so are described below.

See also the related Drupal 8 change record.

How to override the default behavior

  1. If you are using a module such as Security Kit that already writes the X-Frame-Options header on its own, that setting will be automatically respected (pending the patch at #2661644: Integrate with Drupal core clickjacking defense) and Drupal core will not overwrite it. The Security Kit module provides an administrative interface for setting this header, so it's a good choice if you need to override the default Drupal core behavior and aren't sure exactly how to do it.
  2. Alternatively, set the 'x_frame_options' variable via any standard method, for example in settings.php:
      // Turn off the X-Frame-Options header entirely, to restore the previous
      // behavior of allowing the site to be embedded in a frame on another site.
      $conf['x_frame_options'] = '';
    

    or

      // Set the "DENY" option to prevent the site from ever being embedded in a
      // frame at all, even on this site itself.
      $conf['x_frame_options'] = 'DENY';
    

    See https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Frame-Options for more information on the various options this header can take.

    Removing the header (as shown in the first example code snippet above) should not be done lightly, or else your Drupal site could be embedded on other sites and then the user tricked into doing actions they don't want.

  3. If you want to remove the X-Frame-Options header in hook_page_alter() or theme preprocess functions that run later you can remove the header like this (requires PHP >= 5.3):
    header_remove('X-Frame-Options');
    
Impacts: 
Site builders, administrators, editors
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

Michael_Lessard_micles.biz’s picture

I am not at all an expert, but I had added it (before D7.50 came out) in .htaccess as follows :
Header append X-FRAME-OPTIONS "SAMEORIGIN"

Adding it to .htaccess seemed more 'authoritative' than settings.php. My goal was to allow iframe inputs in my nodes, while limiting some possible abuses.

I presume I can leave it in my .htaccess without any impact with the new Drupal core 7.50.

Michael Lessard
webmaster of Quebec City "democracy in action" media

David_Rothstein’s picture

It can be set in .htaccess.

However I wonder if you want Header set X-FRAME-OPTIONS "SAMEORIGIN" (rather than "Header append")? As far as I know "Header append" will add that value to the header that's already there (the one Drupal sets) which would result in the header having multiple values... I'm not sure offhand what browsers do in that situation.

ngocketit’s picture

Is it possible to allow both SAMEORIGIN and ALLOW-FROM? The idea is that iframe can be embedded normally on the same origin (which is obvious) and some other origins of choice (lets say, from another sub-site of the same company). Setting ALLOW-FROM will ignore same origin, which is weird.

xurizaemon’s picture

No. RFC7034 2.1 says,

These values are mutually exclusive; that is, the header field MUST be set to exactly one of the three values.

If you assume that each domain is a site unto itself, it may feel weird that SAMEORIGIN doesn't implicitly include the current site. Considering sites where users can post content (example.org/~xurizaemon, etc), it does make sense to explicitly include SAMEORIGIN in an ALLOW-FROM.

geek-merlin’s picture

Here's a panels solution to punch exactly the holes you need into this:
Panels HTTP Response Header Pane

Anybody’s picture

If you're having trouble with x_frame_options blocking content you don't want to block please see and discuss this issue with us:
#2820340: "X-Frame-Options" deprecated, use "frame-ancestors" in core instead?

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes

Gik000’s picture

The third suggested solution does not work: I recognize that I was allowed to see my embedded Drupal 7 website only with an active login session.

To avoid this problem and make my solution working in any case I created a delivery page alter function

$domains = variable_get('ur_com_xframe_allowed',array('http://www.underadio.it/'));
  //removing frameset limitation for certain referrers
  if(in_array($_SERVER['HTTP_REFERER'],$domains)){
    //setting the variable to false in order to avoid a future setting of the header
    variable_set('x_frame_options', FALSE);
  } else {
    //default behavior
    variable_set('x_frame_options', 'SAMEORIGIN');
  }

I also wrote a blog post about Drupal 7 and X-Frame-Options explaining everything.

Hope this can be helpful.

stewest’s picture

The X-Frame-Options header has been obsoleted by the frame-ancestors directive from Content Security Policy Level 2.

What would the best way forward be now for D7?

There is some talk of this here https://www.drupal.org/project/seckit/issues/2675922

Stew West

renenee’s picture

Is anyone seeing this issue resurface with newer versions of Drupal? Using the $conf['x_frame_options'] = ''; workaround no longer seems to affect the header, as far as I can tell, and it's forcing SAMEORIGIN.

timfluhr’s picture

I found that my /etc/apache2/conf-enabled/ssl-params.conf file explicitly set X-Frame-Options to Deny.

I was actually getting X-Frame-Options set twice in my header...once by the above conf file and once by drupal.

Try running:

curl -I https://yoursite.com

this will display your headers and maybe you have conflicting parameters being set independently.