Helmet helps secure Express apps by setting HTTP response headers.
Get started
Here’s a sample Express app that uses Helmet:
import express from "express";
import helmet from "helmet";
const app = express();
// Use Helmet!
app.use(helmet());
app.get("/", (req, res) => {
res.send("Hello world!");
app.listen(8000);
You can also
require("helmet")
if you prefer.
By default, Helmet sets the following headers:
-
Content-Security-Policy
: A powerful allow-list of what can happen on your page which mitigates many attacks -
Cross-Origin-Opener-Policy
: Helps process-isolate your page -
Cross-Origin-Resource-Policy
: Blocks others from loading your resources cross-origin -
Origin-Agent-Cluster
: Changes process isolation to be origin-based -
Referrer-Policy
: Controls theReferer
header -
Strict-Transport-Security
: Tells browsers to prefer HTTPS -
X-Content-Type-Options
: Avoids MIME sniffing -
X-DNS-Prefetch-Control
: Controls DNS prefetching -
X-Download-Options
: Forces downloads to be saved (Internet Explorer only) -
X-Frame-Options
: Legacy header that mitigates clickjacking attacks -
X-Permitted-Cross-Domain-Policies
: Controls cross-domain behavior for Adobe products, like Acrobat -
X-Powered-By
: Info about the web server. Removed because it could be used in simple attacks -
X-XSS-Protection
: Legacy header that tries to mitigate XSS attacks , but makes things worse, so Helmet disables it
Each header can be configured. For example, here’s how you configure the
Content-Security-Policy
header:
// This sets custom options for the
// Content-Security-Policy header.
app.use(
helmet({
contentSecurityPolicy: {
directives: {
"script-src": ["'self'", "example.com"],
Headers can also be disabled. For example, here’s how you disable the
Content-Security-Policy
and
X-Download-Options
headers:
// This disables the Content-Security-Policy
// and X-Download-Options headers.
app.use(
helmet({
contentSecurityPolicy: false,
xDownloadOptions: false,
Reference
Content-Security-Policy
Default:
Content-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
The
Content-Security-Policy
header mitigates a large number of attacks, such as
cross-site scripting
. See
MDN’s introductory article on Content Security Policy
.
This header is powerful but likely requires some configuration.
To configure this header, pass an object with a nested
directives
object. Each key is a directive name in camel case (such as
defaultSrc
) or kebab case (such as
default-src
). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.
// Sets all of the defaults, but overrides `script-src`
// and disables the default `style-src`.
app.use(
helmet({
contentSecurityPolicy: {
directives: {
"script-src": ["'self'", "example.com"],
"style-src": null,
// Sets the `script-src` directive to
// "'self' 'nonce-e33...'" (or similar)
app.use((req, res, next) => {
res.locals.cspNonce = crypto.randomBytes(32).toString("hex");
next();
app.use(
helmet({
contentSecurityPolicy: {
directives: {
scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
These directives are merged into a default policy, which you can disable by setting
useDefaults
to
false
.
// Sets "Content-Security-Policy: default-src 'self';
// script-src 'self' example.com;object-src 'none';
// upgrade-insecure-requests"
app.use(
helmet({
contentSecurityPolicy: {
useDefaults: false,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
You can get the default directives object with
helmet.contentSecurityPolicy.getDefaultDirectives()
. Here is the default policy (whitespace added for readability):
default-src 'self';
base-uri 'self';
font-src 'self' https: data:;
form-action 'self';
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests
The
default-src
directive can be explicitly disabled by setting its value to
helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc
, but this is not recommended.
You can set the
Content-Security-Policy-Report-Only
instead.
// Sets the Content-Security-Policy-Report-Only header
app.use(
helmet({
contentSecurityPolicy: {
directives: {
/* ... */
reportOnly: true,
Helmet performs very little validation on your CSP. You should rely on CSP checkers like CSP Evaluator instead.
To disable the
Content-Security-Policy
header:
app.use(
helmet({
contentSecurityPolicy: false,
You can use this as standalone middleware with
app.use(helmet.contentSecurityPolicy())
.
Cross-Origin-Embedder-Policy
This header is not set by default.
The
Cross-Origin-Embedder-Policy
header helps control what resources can be loaded cross-origin. See
MDN’s article on this header
for more.
// Helmet does not set Cross-Origin-Embedder-Policy
// by default.
app.use(helmet());
// Sets "Cross-Origin-Embedder-Policy: require-corp"
app.use(helmet({ crossOriginEmbedderPolicy: true }));
// Sets "Cross-Origin-Embedder-Policy: credentialless"
app.use(helmet({ crossOriginEmbedderPolicy: { policy: "credentialless" } }));
You can use this as standalone middleware with
app.use(helmet.crossOriginEmbedderPolicy())
.
Cross-Origin-Opener-Policy
Default:
Cross-Origin-Opener-Policy: same-origin
The
Cross-Origin-Opener-Policy
header helps process-isolate your page. For more, see
MDN’s article on this header
.
// Sets "Cross-Origin-Opener-Policy: same-origin"
app.use(helmet());
// Sets "Cross-Origin-Opener-Policy: same-origin-allow-popups"
app.use(
helmet({
crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" },
To disable the
Cross-Origin-Opener-Policy
header:
app.use(
helmet({
crossOriginOpenerPolicy: false,
You can use this as standalone middleware with
app.use(helmet.crossOriginOpenerPolicy())
.
Cross-Origin-Resource-Policy
Default:
Cross-Origin-Resource-Policy: same-origin
The
Cross-Origin-Resource-Policy
header blocks others from loading your resources cross-origin in some cases. For more, see
“Consider deploying Cross-Origin Resource Policy
and
MDN’s article on this header
.
// Sets "Cross-Origin-Resource-Policy: same-origin"
app.use(helmet());
// Sets "Cross-Origin-Resource-Policy: same-site"
app.use(helmet({ crossOriginResourcePolicy: { policy: "same-site" } }));
To disable the
Cross-Origin-Resource-Policy
header:
app.use(
helmet({
crossOriginResourcePolicy: false,
You can use this as standalone middleware with
app.use(helmet.crossOriginResourcePolicy())
.
Origin-Agent-Cluster
Default:
Origin-Agent-Cluster: ?1
The
Origin-Agent-Cluster
header provides a mechanism to allow web applications to isolate their origins from other processes. Read more about it
in the spec
.
This header takes no options and is set by default.
// Sets "Origin-Agent-Cluster: ?1"
app.use(helmet());
To disable the
Origin-Agent-Cluster
header:
app.use(
helmet({
originAgentCluster: false,
You can use this as standalone middleware with
app.use(helmet.originAgentCluster())
.
Referrer-Policy
Default:
Referrer-Policy: no-referrer
The
Referrer-Policy
header which controls what information is set in
the
Referer
request header
. See
“Referer header: privacy and security concerns”
and
the header’s documentation
on MDN for more.
// Sets "Referrer-Policy: no-referrer"
app.use(helmet());
policy
is a string or array of strings representing the policy. If passed as an array, it will be joined with commas, which is useful when setting
a fallback policy
. It defaults to
no-referrer
.
// Sets "Referrer-Policy: no-referrer"
app.use(
helmet({
referrerPolicy: {
policy: "no-referrer",
// Sets "Referrer-Policy: origin,unsafe-url"
app.use(
helmet({
referrerPolicy: {
policy: ["origin", "unsafe-url"],
To disable the
Referrer-Policy
header:
app.use(
helmet({
referrerPolicy: false,
You can use this as standalone middleware with
app.use(helmet.referrerPolicy())
.
Strict-Transport-Security
Default:
Strict-Transport-Security: max-age=15552000; includeSubDomains
The
Strict-Transport-Security
header tells browsers to prefer HTTPS instead of insecure HTTP. See
the documentation on MDN
for more.
// Sets "Strict-Transport-Security: max-age=15552000; includeSubDomains"
app.use(helmet());
maxAge
is the number of seconds browsers should remember to prefer HTTPS. If passed a non-integer, the value is rounded down. It defaults to
15552000
, which is 180 days.
includeSubDomains
is a boolean which dictates whether to include the
includeSubDomains
directive, which makes this policy extend to subdomains. It defaults to
true
.
preload
is a boolean. If true, it adds the
preload
directive, expressing intent to add your HSTS policy to browsers. See
the “Preloading Strict Transport Security” section on MDN
for more. It defaults to
false
.
// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains"
app.use(
helmet({
strictTransportSecurity: {
maxAge: 123456,
// Sets "Strict-Transport-Security: max-age=123456"
app.use(
helmet({
strictTransportSecurity: {
maxAge: 123456,
includeSubDomains: false,
// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload"
app.use(
helmet({
strictTransportSecurity: {
maxAge: 63072000,
preload: true,
To disable the
Strict-Transport-Security
header:
app.use(
helmet({
strictTransportSecurity: false,
You can use this as standalone middleware with
app.use(helmet.strictTransportSecurity())
.
X-Content-Type-Options
Default:
X-Content-Type-Options: nosniff
The
X-Content-Type-Options
mitigates
MIME type sniffing
which can cause security issues. See
documentation for this header on MDN
for more.
This header takes no options and is set by default.
// Sets "X-Content-Type-Options: nosniff"
app.use(helmet());
To disable the
X-Content-Type-Options
header:
app.use(
helmet({
xContentTypeOptions: false,
You can use this as standalone middleware with
app.use(helmet.xContentTypeOptions())
.
X-DNS-Prefetch-Control
Default:
X-DNS-Prefetch-Control: off
The
X-DNS-Prefetch-Control
header helps control DNS prefetching, which can improve user privacy at the expense of performance. See
documentation on MDN
for more.
// Sets "X-DNS-Prefetch-Control: off"
app.use(helmet());
allow
is a boolean dictating whether to enable DNS prefetching. It defaults to
false
.
Examples:
// Sets "X-DNS-Prefetch-Control: off"
app.use(
helmet({
xDnsPrefetchControl: { allow: false },
// Sets "X-DNS-Prefetch-Control: on"
app.use(
helmet({
xDnsPrefetchControl: { allow: true },
To disable the
X-DNS-Prefetch-Control
header and use the browser’s default value:
app.use(
helmet({
xDnsPrefetchControl: false,
You can use this as standalone middleware with
app.use(helmet.xDnsPrefetchControl())
.
X-Download-Options
Default:
X-Download-Options: noopen
The
X-Download-Options
header is specific to Internet Explorer 8. It forces potentially-unsafe downloads to be saved, mitigating execution of HTML in your site’s context. For more, see
this old post on MSDN
.
This header takes no options and is set by default.
// Sets "X-Download-Options: noopen"
app.use(helmet());
To disable the
X-Download-Options
header:
app.use(
helmet({
xDownloadOptions: false,
You can use this as standalone middleware with
app.use(helmet.xDownloadOptions())
.
X-Frame-Options
Default:
X-Frame-Options: SAMEORIGIN
The legacy
X-Frame-Options
header to help you mitigate
clickjacking attacks
. This header is superseded by
the
frame-ancestors
Content Security Policy directive
but is still useful on old browsers or if no CSP is used. For more, see
the documentation on MDN
.
// Sets "X-Frame-Options: SAMEORIGIN"
app.use(helmet());
action
is a string that specifies which directive to use—either
DENY
or
SAMEORIGIN
. (A legacy directive,
ALLOW-FROM
, is not supported by Helmet.
Read more here.
) It defaults to
SAMEORIGIN
.
Examples:
// Sets "X-Frame-Options: DENY"
app.use(
helmet({
xFrameOptions: { action: "deny" },
// Sets "X-Frame-Options: SAMEORIGIN"
app.use(
helmet({
xFrameOptions: { action: "sameorigin" },
To disable the
X-Frame-Options
header:
app.use(
helmet({
xFrameOptions: false,
You can use this as standalone middleware with
app.use(helmet.xFrameOptions())
.
X-Permitted-Cross-Domain-Policies
Default:
X-Permitted-Cross-Domain-Policies: none
The
X-Permitted-Cross-Domain-Policies
header tells some clients (mostly Adobe products) your domain’s policy for loading cross-domain content. See
the description on OWASP
for more.
// Sets "X-Permitted-Cross-Domain-Policies: none"
app.use(helmet());
permittedPolicies
is a string that must be
"none"
,
"master-only"
,
"by-content-type"
, or
"all"
. It defaults to
"none"
.
Examples:
// Sets "X-Permitted-Cross-Domain-Policies: none"
app.use(
helmet({
xPermittedCrossDomainPolicies: {
permittedPolicies: "none",
// Sets "X-Permitted-Cross-Domain-Policies: by-content-type"
app.use(
helmet({
xPermittedCrossDomainPolicies: {
permittedPolicies: "by-content-type",
To disable the
X-Permitted-Cross-Domain-Policies
header:
app.use(
helmet({
xPermittedCrossDomainPolicies: false,
You can use this as standalone middleware with
app.use(helmet.xPermittedCrossDomainPolicies())
.
X-Powered-By
Default: the
X-Powered-By
header, if present, is removed.
Helmet removes the
X-Powered-By
header, which is set by default in Express and some other frameworks. Removing the header offers very limited security benefits (see
this discussion
) and is mostly removed to save bandwidth, but may thwart simplistic attackers.
Note:
Express has a built-in way to disable the
X-Powered-By
header
, which you may wish to use instead.
The removal of this header takes no options. The header is removed by default.
To disable this behavior:
// Not required, but recommended for Express users:
app.disable("x-powered-by");
// Ask Helmet to ignore the X-Powered-By header.
app.use(
helmet({
xPoweredBy: false,
You can use this as standalone middleware with
app.use(helmet.xPoweredBy())
.
X-XSS-Protection
Default:
X-XSS-Protection: 0
Helmet disables browsers’ buggy cross-site scripting filter by setting the legacy
X-XSS-Protection
header to
0
. See
discussion about disabling the header here
and
documentation on MDN
.
This header takes no options and is set by default.
To disable the
X-XSS-Protection
header:
// This is not recommended.