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.