Web application developer
PHP, Yii, MySQL, Node.js - JavaScript, HTML, CSS & SASS - Linux, AWS & serverless
The X-Frame-Options
HTTP header is one of the HTTP security headers available to enhance the security of a website or web application. Although it is made obsolete by the frame-ancestors
directive available in the Content-Security-Policy
header, browsers still support X-Frame-Options and it can be used to manage or prevent the framing of your sites' content in other websites.
X-Frame-Options
is a response header generated by a server in response to an HTTP request, and it can be used to prevent rendering of the page in <frame>
, <iframe>
, <embed>
, <object>
HTML elements.
Like all the HTTP security headers, this header must be set in an HTTP response by your web server or content delivery mechanism. That means using a server-side scripting language like PHP or Node.js or a web server framework like Apache or Nginx. When working with AWS CloudFront, perhaps for static sites deployed to S3 or apps running through API Gateway, it's possible to use Lambda@Edge or CloudFront functions to add headers into the viewer response.
Sites can use the X-Frame-Options
header to ensure that their content is not embedded and rendered on other sites, helping to prevent click-jacking attacks and malicious rendering of your content across the web.
X-Frame-Options
has only two possible values which are simple string values:
X-Frame-Options: DENY
DENY
indicates to the browser that the page cannot be displayed in a frame in any location, even framed with the same site and domain.
X-Frame-Options: SAMEORIGIN
SAMEORIGIN
indicates to the browser that the page can be framed within the same host origin. An example use-case for this directive is when using Yii 2's debugger for local development, as this module loads a framed window originating from the same host, and will be blocked if the DENY
directive is used.
There is a deprecated directive of ALLOW-FROM=url
which previously offered the ability to list permitted domains, however this is now unsupported and you should use the frame-ancestors
directive available in the Content-Security-Policy
header for this purpose.
The h5bp/server-configs-apache library is a great reference for this (this version from v6.0.0, 5th December 2022):
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY" "expr=%{CONTENT_TYPE} =~ m#text/html#i"
</IfModule>
<?php
header('X-Frame-Options: DENY');
?>
For Yii2, headers can be added site-wide by modifying the response
object in the app config (thanks to this SO post):
'components' => [
'response' => [
'on beforeSend' => function($event) {
$event->sender->headers->add('X-Frame-Options', 'DENY');
},
],
Note that Apache/.htaccess settings of a header will overwrite any value set in PHP.
In the Remix JavaScript framework response headers are set in the handleRequest
function of the server entry script, typically app/entry.server.jsx
.
import { RemixServer } from "@remix-run/react";
import { renderToString } from "react-dom/server";
export default function handleRequest(
request,
responseStatusCode,
responseHeaders,
remixContext
) {
let markup = renderToString(
<RemixServer context={remixContext} url={request.url} />
);
responseHeaders.set("Content-Type", "text/html");
// Set X-Frame-Options Header
responseHeaders.set("X-Frame-Options", "SAMEORIGIN");
return new Response("<!DOCTYPE html>" + markup, {
status: responseStatusCode,
headers: responseHeaders,
});
}
See more information on Remix entry scripts here: https://remix.run/docs/en/v1/guides/migrating-react-router-app#creating-server-and-browser-entrypoints