Skip to content

Instantly share code, notes, and snippets.

@tannerhodges
Last active August 7, 2020 15:21
Show Gist options
  • Save tannerhodges/3bc9b4c8e0fabf5e7096a0190830da8f to your computer and use it in GitHub Desktop.
Save tannerhodges/3bc9b4c8e0fabf5e7096a0190830da8f to your computer and use it in GitHub Desktop.
HTTP Security Headers for Nginx & PHP
# Add HTTP Headers to improve site security.
# https://owasp.org/www-project-secure-headers/#tab=Headers
# X-Frame-Options: Stop people from loading your site in an iframe on their own site.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
add_header X-Frame-Options "SAMEORIGIN";
# X-XSS-Protection: Stop pages from loading when the browser detects cross-site scripting (XSS) attacks.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
add_header X-XSS-Protection "1; mode=block";
# X-Content-Type-Options: Prevents IE & Chrome from MIME-sniffing responses away from their declared content-type.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
add_header X-Content-Type-Options "nosniff";
# Strict-Transport-Security (aka "HSTS"): Tell browsers they should only access this site using HTTPS (not HTTP).
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
# https://scotthelme.co.uk/hsts-the-missing-link-in-tls/
add_header Strict-Transport-Security "max-age=31536000; preload";
# Content Security Policy
# Restrict what types of requests can run on our site. Helps prevent XSS, data injection, etc.
#
# - default-src - Default rules for all content.
# - 'unsafe-inline' - Allow inline scripts.
# - 'unsafe-eval' - Allow eval scripts (e.g., in Vue development mode).
# - https: - Only allow assets served over HTTPS.
# - data: - Allow data URIs (e.g., SVG background-images).
# - block-all-mixed-content - Prevent insecure content from loading on the site.
# - upgrade-insecure-requests - Replace insecure HTTP requests with HTTPS ones instead.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests
# https://scotthelme.co.uk/content-security-policy-an-introduction/
add_header Content-Security-Policy "default-src 'unsafe-inline' 'unsafe-eval' https: data:; block-all-mixed-content; upgrade-insecure-requests";
<?php
/**
* Add HTTP Headers to improve site security.
* @see https://owasp.org/www-project-secure-headers/#tab=Headers
*
* Based on the _excellent_ HTTP Headers plugin by Dimitar Ivanov.
* @see https://github.com/riverside/http-headers
*
* The only reason we don't use that plugin is because it doesn't
* have a Network-level admin to easily control headers for the
* entire site. Otherwise, I'd use it in a heartbeat.
*
* For now, the simplest way to maintain sitewide headers is to
* load them through a custom plugin.
*
* P.S. We also _have_ to do this via PHP because Pantheon locks
* down their server Nginx configs.
*/
function add_security_headers() {
$headers = [
/**
* X-Frame-Options
* ----------------
* Stop people from loading your site in an iframe on their own site.
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
*/
'X-Frame-Options' => 'SAMEORIGIN',
/**
* X-XSS-Protection
* ----------------
* Stop pages from loading when the browser detects cross-site scripting (XSS) attacks.
* Mostly for users of older web browsers that don't yet support `Content-Security-Policy`.
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
*/
'X-XSS-Protection' => '1; mode=block',
/**
* X-Content-Type-Options
* ----------------------
* Prevents IE & Chrome from MIME-sniffing responses away from their declared content-type.
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
*/
'X-Content-Type-Options' => 'nosniff',
/**
* Strict-Transport-Security (aka "HSTS")
* --------------------------------------
* Tell browsers they should only access this site using HTTPS (not HTTP).
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
* @see https://scotthelme.co.uk/hsts-the-missing-link-in-tls/
*/
'Strict-Transport-Security' => 'max-age=31536000; preload',
/**
* Content Security Policy
* -----------------------
* Restrict what types of requests can run on our site. Helps prevent XSS, data injection, etc.
*
* Here's what each piece of this header means:
*
* - default-src - Default rules for all content.
* - 'unsafe-inline' - Allow inline scripts.
* - 'unsafe-eval' - Allow eval scripts (e.g., in Vue development mode).
* - https: - Only allow assets served over HTTPS.
* - data: - Allow data URIs (e.g., SVG background-images).
* - block-all-mixed-content - Prevent insecure content from loading on the site.
* - upgrade-insecure-requests - Replace insecure HTTP requests with HTTPS ones instead.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests
* @see https://scotthelme.co.uk/content-security-policy-an-introduction/
*/
'Content-Security-Policy' => "default-src 'unsafe-inline' 'unsafe-eval' https: data:; block-all-mixed-content; upgrade-insecure-requests",
];
/**
* Add all headers to the current response.
* NOTE: This replaces any duplicate headers from other plugins.
* @see https://www.php.net/manual/en/function.header.php
*/
foreach ( $headers as $key => $value ) {
header( sprintf( "%s: %s", $key, $value ) );
}
}
// NOTE: For WordPress, add headers to all non-admin enqueues, actions, and filters.
// if ( ! is_admin() ) {
// add_action('send_headers', '\CCDC\SecurityHeaders\add_headers');
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment