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
.