Helmet для JavaScript (Node.js): полное руководство с примерами
1. Что это и зачем нужна
Helmet — это популярная библиотека для Node.js, которая помогает защитить веб-приложения на базе Express (или совместимых фреймворков) от широкого спектра веб-уязвимостей. Она делает это путём установки различных HTTP-заголовков безопасности. Вместо того чтобы вручную настраивать каждый заголовок, разработчик может подключить Helmet и получить «из коробки» защиту от таких атак, как Cross-Site Scripting (XSS), Clickjacking, MIME-type sniffing и многих других.
Зачем это нужно? HTTP-заголовки — это первая линия обороны вашего приложения. Браузеры, получив правильные заголовки, могут автоматически блокировать опасные действия. Например, заголовок X-Content-Type-Options: nosniff запрещает браузеру «угадывать» MIME-тип ответа, что предотвращает атаки, связанные с загрузкой вредоносных скриптов под видом изображений. Без Helmet разработчику пришлось бы вручную добавлять middleware для каждого такого заголовка, что чревато ошибками и пропусками.
Helmet не является серебряной пулей и не заменяет другие меры безопасности (валидацию ввода, защиту от SQL-инъекций, использование HTTPS). Однако это критически важный и простой шаг для повышения безопасности любого Express-приложения. Библиотека активно поддерживается, имеет огромное сообщество и используется в тысячах проектов по всему миру.
2. Установка
Установка Helmet производится через менеджер пакетов npm (или yarn). Убедитесь, что у вас установлен Node.js и npm.
npm install helmet
Если вы используете yarn:
yarn add helmet
После установки библиотека готова к использованию. Никаких дополнительных зависимостей не требуется.
3. Быстрый старт — минимальный рабочий пример
Самый простой способ начать использовать Helmet — подключить его как middleware для всего приложения. Это активирует все стандартные middleware, входящие в состав Helmet.
const express = require('express');
const helmet = require('helmet');
const app = express();
// Подключаем Helmet как глобальный middleware
app.use(helmet());
app.get('/', (req, res) => {
res.send('Hello, secure world!');
});
app.listen(3000, () => {
console.log('Server started on http://localhost:3000');
});
После запуска этого кода, все ответы вашего сервера будут содержать набор защитных HTTP-заголовков. Вы можете проверить это, открыв инструменты разработчика в браузере (вкладка Network) и посмотрев заголовки ответа.
4. Основные методы/функции/классы
Helmet предоставляет как единую функцию helmet(), которая включает все middleware, так и отдельные функции для каждого заголовка. Это позволяет гибко настраивать защиту.
4.1. helmet() (глобальный middleware)
Сигнатура: helmet(options?: object)
Что делает: Возвращает middleware-функцию, которая устанавливает все стандартные заголовки безопасности. Можно передать объект options для отключения или настройки отдельных middleware.
// Отключаем заголовок Content-Security-Policy, так как будем настраивать его вручную
app.use(helmet({
contentSecurityPolicy: false,
}));
4.2. helmet.contentSecurityPolicy()
Сигнатура: helmet.contentSecurityPolicy(options?: object)
Что делает: Устанавливает заголовок Content-Security-Policy (CSP). Это один из самых мощных инструментов защиты от XSS-атак. Он позволяет указать браузеру, какие источники (скрипты, стили, изображения и т.д.) являются доверенными.
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "trusted-cdn.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "images.example.com"],
},
})
);
4.3. helmet.crossOriginEmbedderPolicy()
Сигнатура: helmet.crossOriginEmbedderPolicy(options?: object)
Что делает: Устанавливает заголовок Cross-Origin-Embedder-Policy. Требует, чтобы все ресурсы, загружаемые на страницу, были явно разрешены через Cross-Origin-Resource-Policy или CORS. Это часть стратегии защиты от Spectre и Meltdown.
app.use(helmet.crossOriginEmbedderPolicy({ policy: "require-corp" }));
4.4. helmet.crossOriginOpenerPolicy()
Сигнатура: helmet.crossOriginOpenerPolicy(options?: object)
Что делает: Устанавливает заголовок Cross-Origin-Opener-Policy. Ограничивает возможность взаимодействия с окном, открытым через window.open() или ссылку с target="_blank". Помогает изолировать документы друг от друга.
app.use(helmet.crossOriginOpenerPolicy({ policy: "same-origin" }));
4.5. helmet.crossOriginResourcePolicy()
Сигнатура: helmet.crossOriginResourcePolicy(options?: object)
Что делает: Устанавливает заголовок Cross-Origin-Resource-Policy. Сообщает браузеру, какие сайты могут загружать данный ресурс. Это более тонкая настройка, чем CORS, и работает на уровне браузера.
app.use(helmet.crossOriginResourcePolicy({ policy: "same-site" }));
4.6. helmet.expectCt()
Сигнатура: helmet.expectCt(options?: object)
Что делает: Устанавливает заголовок Expect-CT. Позволяет сайтам сообщать браузерам о необходимости проверки сертификатов через Certificate Transparency. Это помогает обнаружить мошеннические или неправильно выпущенные SSL-сертификаты.
app.use(helmet.expectCt({ maxAge: 86400, enforce: true, reportUri: "https://example.com/report" }));
4.7. helmet.frameguard()
Сигнатура: helmet.frameguard(options?: object)
Что делает: Устанавливает заголовок X-Frame-Options. Защищает от Clickjacking-атак, запрещая или ограничивая отображение страницы во фреймах (<frame>, <iframe>).
// Запрещаем отображение во фреймах полностью
app.use(helmet.frameguard({ action: 'deny' }));
// Разрешаем только для того же источника
app.use(helmet.frameguard({ action: 'sameorigin' }));
4.8. helmet.hidePoweredBy()
Сигнатура: helmet.hidePoweredBy(options?: object)
Что делает: Удаляет заголовок X-Powered-By. Этот заголовок часто раскрывает информацию о технологии, на которой работает сервер (например, Express), что может помочь злоумышленнику подобрать уязвимости.
app.use(helmet.hidePoweredBy());
4.9. helmet.hsts()
Сигнатура: helmet.hsts(options?: object)
Что делает: Устанавливает заголовок Strict-Transport-Security (HSTS). Предписывает браузеру всегда использовать HTTPS для соединения с сервером, даже если пользователь ввел HTTP-адрес. Это защищает от атак типа "человек посередине" (MITM).
app.use(helmet.hsts({ maxAge: 31536000, includeSubDomains: true, preload: true }));
4.10. helmet.ieNoOpen()
Сигнатура: helmet.ieNoOpen(options?: object)
Что делает: Устанавливает заголовок X-Download-Options: noopen. Это специфическая для Internet Explorer директива, которая предотвращает выполнение загруженных HTML-файлов в контексте вашего сайта.
app.use(helmet.ieNoOpen());
4.11. helmet.noSniff()
Сигнатура: helmet.noSniff(options?: object)
Что делает: Устанавливает заголовок X-Content-Type-Options: nosniff. Запрещает браузеру "угадывать" (sniff) MIME-тип ответа. Браузер должен строго следовать значению заголовка Content-Type. Это предотвращает атаки, когда вредоносный скрипт маскируется под изображение.
app.use(helmet.noSniff());
4.12. helmet.originAgentCluster()
Сигнатура: helmet.originAgentCluster(options?: object)
Что делает: Устанавливает заголовок Origin-Agent-Cluster. Предоставляет браузеру подсказку о том, что документ должен быть изолирован в отдельном процессе, что может улучшить производительность и безопасность.
app.use(helmet.originAgentCluster());
4.13. helmet.permittedCrossDomainPolicies()
Сигнатура: helmet.permittedCrossDomainPolicies(options?: object)
Что делает: Устанавливает заголовок X-Permitted-Cross-Domain-Policies. Этот заголовок используется Adobe Flash и Adobe Acrobat для управления тем, какие политики кросс-доменного доступа разрешены.
app.use(helmet.permittedCrossDomainPolicies({ permittedPolicies: 'none' }));
4.14. helmet.referrerPolicy()
Сигнатура: helmet.referrerPolicy(options?: object)
Что делает: Устанавливает заголовок Referrer-Policy. Контролирует, какой объем информации о реферере (предыдущей странице) передается при переходе по ссылке. Это помогает защитить конфиденциальность пользователей.
app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' }));
4.15. helmet.xssFilter()
Сигнатура: helmet.xssFilter(options?: object)
Что делает: Устанавливает заголовок X-XSS-Protection: 0. Важно: в современных браузерах этот заголовок устарел и может быть вреден. Helmet устанавливает его в 0, чтобы отключить встроенный (и часто проблемный) XSS-фильтр браузера, полагаясь на более надежный CSP.
app.use(helmet.xssFilter());
5. Реальный практический пример (100-200 строк кода)
Ниже представлен пример полноценного Express-приложения с использованием Helmet. Приложение имеет несколько маршрутов, статическую папку и настроенную политику безопасности.
const express = require('express');
const helmet = require('helmet');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
// 1. Базовая настройка Helmet
app.use(helmet());
// 2. Тонкая настройка CSP (переопределяем стандартную)
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "cdnjs.cloudflare.com"],
styleSrc: ["'self'", "'unsafe-inline'", "fonts.googleapis.com"],
fontSrc: ["'self'", "fonts.gstatic.com"],
imgSrc: ["'self'", "data:", "images.unsplash.com"],
connectSrc: ["'self'", "api.example.com"],
frameAncestors: ["'