Skip to main content

Helmet

Helmet помогает защитить Express-приложения посредством установки HTTP-заголовков, связанных с безопасностью. "Это не серебряная пуля, но может помочь!"

Быстрый старт

Установка:

yarn add helmet
# или
npm i helmet

Использование:

const express = require('express')
const helmet = require('helmet')

const app = express()

app.use(helmet())

Как это работает?

Helmet - это посредник (middleware) для Express-приложений.

Функция высшего уровня helmet - это обертка для 15 небольших посредников, 11 из которых включены по умолчанию:

// это
app.use(helmet())

// эквивалентно следующему
app.use(helmet.contentSecurityPolicy())
app.use(helmet.dnsPrefetchControl())
app.use(helmet.expectCt())
app.use(helmet.frameguard())
app.use(helmet.hidePoweredBy())
app.use(helmet.hsts())
app.use(helmet.ieNoOpen())
app.use(helmet.noSniff())
app.use(helmet.permittedCrossDomainPolicies())
app.use(helmet.referrerPolicy())
app.use(helmet.xssFilter())

Пример кастомизации одного из указанных посредников:

app.use(
helmet({
referrerPolicy: { policy: 'no-referrer' },
})
)

Пример отключения посредника:

app.use(
helmet({
contentSecurityPolicy: false,
})
)

API

helmet(options)

Как было отмечено, 11 из 15 названных выше посредников включены по умолчанию. crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy и originAgentCluster по умолчанию отключены. Они должны включаться вручную. Как обещают разработчики helmet, эти заголовки будут включены по умолчанию в следующей мажорной версии helmet.

// включаем все 11 посредников
app.use(helmet())

Пример отключения посредника frameguard:

// включаем 10 посредников, отключаем `helmet.frameguard`
app.use(
helmet({
frameguard: false,
})
)

Большинство посредников принимает объект с настройками (см. ниже). Пример настройки frameguard:

app.use(
helmet({
frameguard: {
action: 'deny',
},
})
)

Обратите внимание: каждый из посредников, входящих в состав helmet, может использоваться в качестве автономного модуля, т.е. устанавливаться и применяться отдельно.

helmet.contentSecurityPolicy(options)

helmet.contentSecurityPolicy устанавливает заголовок Content-Security-Policy, который, кроме прочего, помогает предотвращать межсайтовый скриптинг. Данный заголовок определяет источники, из которых могут загружаться ресурсы, используемые приложением.

options.directives - это объект. Ключи данного объекта - это названия соответствующих директив в стиле camel case (defaultSrc) или kebab case (default-src). Каждое значение - это итерируемая сущность (как правило, массив), состоящая из строк или функций для каждой директивы. Если в итераторе имеется функция, она вызывается с объектами запроса и ответа (req и res, соответственно). default-src может быть отключена с помощью helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc.

options.reportOnly - логическое значение, по умолчанию false. Если true, устанавливается заголовок Content-Security-Policy-Report-Only.

По умолчанию применяются следующие директивы:

default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: data:;
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

Эти директивы можно использовать, установив значение настройки options.useDefaults в true. Получить их можно с помощью helmet.contentSecurityPolicy.getDefaultDirectives().

Примеры:

// устанавливаем дефолтные директивы, перезаписываем `script-src` и отключаем `style-src`
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
'script-src': [`'self'`, 'example.com'],
'style-src': null,
},
})
)

// устанавливаем `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: [],
},
})
)

// устанавливаем заголовок `Content-Security-Policy-Report-Only`
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
// ...
},
reportOnly: true,
})
)

// устанавливаем директиву `script-src` в значение `'self' 'nonce-e33ccde670f149c1789b1e1e113b0916'`
app.use((_, res, next) => {
res.locals.cspNonce = crypto.randomBytes(16).toString('hex')
next()
})
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
scriptSrc: [`'self'`, (req, res) => `'none-${res.locals.cspNonce}'`],
},
})
)

// отключаем `default-src` и устанавливаем `Content-Security-Policy: script-src 'self'`
app.use(
helmet.contentSecurityPolicy({
useDefaults: false,
directives: {
'default-src': helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc,
'script-src': [`'self'`],
},
})
)

helmet.crossOriginEmbedderPolicy()

helmet.crossOriginEmbedderPolicy устанавливает заголовок Cross-Origin-Embedder-Policy в значение require-corp. Данный заголовок запрещает загрузку ресурсов из других источников при отсутствии явного разрешения, предоставленного с помощью CORP или CORS.

Данный посредник не включается по умолчанию при вызове helmet() и должен быть включен вручную.

app.use(helmet({ crossOriginEmbedderPolicy: true }))

helmet.crossOriginOpenerPolicy()

helmet.crossOriginOpenerPolicy устанавливает заголовок Cross-Origin-Opener-Policy. Данный заголовок запрещает делиться группой контекста области просмотра с другими источниками. Это означает, что приложение нельзя будет открыть в попапе.

Данный посредник также не включается по умолчанию при вызове helmet() и должен быть включен вручную.

app.use({ helmet({ crossOriginOpenerPolicy: true }) })

// разрешаем загрузку документа в собственные попапы
app.use(
helmet({
crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' }
})
)

helmet.crossOriginResourcePolicy устанавливает заголовок Cross-Origin-Resource-Policy. Данный заголовок блокирует no-cors запросы из других источников. Использовать его в продакшне не рекомендуется.

helmet.expectCt устанавливает заголовок Expect-CT, помогающий определять неправильно выданные сертификаты.

helmet.referrerPolicy(options)

helmet.referrerPolicy устанавливает заголовок Referrer-Policy, который определяет, какая информация указывается в заголовке Referer.

options.policy - это строка или массив строк, представляющие политику. Если передан массив, он будет объединен с помощью запятой, что может быть использовано для установки резервной политики. Значением по умолчанию является no-referrer.

helmet.hsts(options)

helmet.hsts устанавливает заголовок Strict-Transport-Security, который инструктирует браузер использовать HTTPS вместо HTTP.

options.maxAge - это количество секунд, в течение которых браузер должен предпочитать HTTPS. Если передано дробное число, оно округляется. Значением по умолчанию является 15552000 (180 дней).

options.includeSubdomains - логическое значение, определяющее, распространяется ли требование на поддомены. По умолчанию имеет значение true.

options.preload - логическое значение. Если true, добавляется директива preload, выражающая намерение использовать политику HSTS. По умолчанию имеет значение false.

helmet.noSniff устанавливает заголовок X-Content-Type-Options в значение nosniff. Это позволяет предотвратить MIME sniffing.

helmet.originAgentCluster устанавливает заголовок Origin-Agent-Cluster, предоставляющий механизм, позволяющий веб-приложениям изолировать свои источники. В настоящее время данный заголовок поддерживается только Google Chrome.

helmet.dnsPrefetchControl(options)

helmet.dnsPrefetchControl устанавливает заголовок X-DNS-Prefetch-Control для управления предварительным получением DNS, что может улучшить приватность пользователей за счет производительности. Предварительное получение DNS - это функция, с помощью которой браузеры заранее выполняют разрешение доменного имени как для ссылок, которые пользователь может использовать для перехода на другую страницу, так и для URL-адресов ресурсов, используемых приложением, таких как изображения, CSS, JavaScript и т.д. Почитать о preload, prefetch и подобных тегах можно здесь.

options.allow - логическое значение, индикатор включения предварительного получения DNS. По умолчанию имеет значение false.

helmet.ieNoOpen устанавливает специфичный для IE8 заголовок X-Download-Options.

helmet.frameguard(options)

helmet.frameguard устанавливает заголовок X-Frame-Options, который помогает предотвращать кликджекинг. Данный заголовок нужен для старых браузеров, которые не поддерживают директиву frame-ancestors политики CSP.

options.action - это строка, определяющая используемую директиву. Она может иметь два значения: DENY или SAMEORIGIN. Значением по умолчанию является SAMEORIGIN.

helmet.permittedCrossDomainPolicies устанавливает заголовок X-Permitted-Cross-Domain-Policies, который определяет политику для загрузки контента из других источников для клиентов (в основном, продуктов Adobe).

helmet.hidePoweredBy() удаляет заголовок X-Powered-By. В случае с express следует использовать app.disable('x-powered-by').

helmet.xssFilter() устанавливает заголовок X-XSS-Protection в значение 0. Данный заголовок также нужен только для старых браузеров, плохо поддерживающих CSP.