Пошук уроків, статей та іншого контенту
Налаштуєте Helmet для автоматичного додавання захисних HTTP-заголовків і зменшення типових вебризиків.
Helmet — це набір middleware для Node.js, який додає до HTTP-відповідей заголовки безпеки.
У NestJS Helmet допомагає зменшити ризики, пов’язані з:
виконанням небажаних скриптів;
вбудовуванням сторінки в iframe;
неправильним визначенням типу вмісту;
витоком інформації через заголовок Referer;
небажаним використанням HTTP замість HTTPS.
Helmet не захищає застосунок від усіх атак. Він не замінює автентифікацію, авторизацію, перевірку вхідних даних або правильне керування секретами. Його завдання — встановити безпечні значення HTTP-заголовків за замовчуванням.
Для стандартного NestJS-застосунку з Express встановіть пакет:
npm install helmetЗа замовчуванням NestJS використовує Express, якщо під час створення застосунку не було обрано Fastify.
Helmet потрібно підключити до створення маршрутів. У NestJS це зазвичай роблять у файлі src/main.ts.
import { NestFactory } from '@nestjs/core';
import helmet from 'helmet';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Додаємо заголовки безпеки до HTTP-відповідей
app.use(helmet());
await app.listen(3000);
}
bootstrap();Після цього запущений застосунок автоматично додаватиме заголовки, які встановлює Helmet.
Перевірити їх можна за допомогою curl:
curl -I http://localhost:3000Серед заголовків відповіді можна побачити, наприклад:
Content-Security-Policy: default-src 'self';base-uri 'self';...
Cross-Origin-Opener-Policy: same-origin
Origin-Agent-Cluster: ?1
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGINНабір заголовків залежить від версії Helmet та його налаштувань.
Content-Security-PolicyContent-Security-Policy, або CSP, визначає, звідки браузер може завантажувати скрипти, стилі, зображення та інші ресурси.
Наприклад:
Content-Security-Policy: default-src 'self'Це означає, що за замовчуванням ресурси дозволені лише з того самого джерела.
CSP допомагає зменшити наслідки XSS-атак. Якщо зловмиснику вдасться вставити скрипт на сторінку, браузер може заблокувати його виконання.
Helmet встановлює CSP за замовчуванням. Це добре для безпеки, але іноді може вплинути на frontend-частину застосунку, якщо вона використовує:
зовнішні CDN;
inline-скрипти;
inline-стилі;
зображення із зовнішніх доменів.
Для API, який не віддає HTML-сторінки, CSP зазвичай не створює проблем. Якщо NestJS також обслуговує frontend, політику потрібно перевірити в браузері та налаштувати відповідно до реальних джерел ресурсів.
X-Content-Type-OptionsHelmet додає:
X-Content-Type-Options: nosniffЦей заголовок забороняє браузеру намагатися «вгадати» тип відповіді замість використання значення Content-Type.
Наприклад, якщо сервер повідомив, що файл є текстом, браузер не повинен самостійно трактувати його як JavaScript.
X-Frame-OptionsHelmet додає заголовок, який забороняє або обмежує вбудовування сторінки в iframe.
Це допомагає захиститися від clickjacking — атаки, коли користувач взаємодіє з невидимою або замаскованою сторінкою.
Типове значення:
X-Frame-Options: SAMEORIGINВоно дозволяє вбудовування лише сторінками з того самого джерела.
Referrer-PolicyЦей заголовок визначає, яку інформацію про попередню сторінку браузер передаватиме в заголовку Referer.
Helmet встановлює обмежувальну політику, щоб зменшити випадковий витік URL-адрес і параметрів.
Strict-Transport-SecurityЗаголовок HSTS повідомляє браузеру, що застосунок потрібно відкривати через HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomainsПісля отримання такого заголовка браузер певний час автоматично замінюватиме HTTP на HTTPS для цього домену.
HSTS слід використовувати лише тоді, коли production-застосунок справді доступний через HTTPS. Під час локальної розробки його часто вимикають, щоб не створювати проблем із тестуванням через HTTP.
У production варто використовувати Helmet повністю, а в локальному середовищі можна вимкнути HSTS:
import { NestFactory } from '@nestjs/core';
import helmet from 'helmet';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const isProduction = process.env.NODE_ENV === 'production';
app.use(
helmet({
// HSTS потрібен для HTTPS у production
strictTransportSecurity: isProduction ? undefined : false,
}),
);
await app.listen(3000);
}
bootstrap();У production перед запуском застосунку потрібно встановити змінну середовища:
NODE_ENV=production npm run startСаме вимкнення HSTS у development не означає, що інші заголовки безпеки потрібно вимикати.
Helmet дозволяє змінювати окремі middleware через параметри:
import { NestFactory } from '@nestjs/core';
import helmet from 'helmet';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(
helmet({
// Дозволяємо сторінкам того самого джерела використовувати iframe
frameguard: {
action: 'sameorigin',
},
// Встановлюємо політику, яка не передає URL попередньої сторінки
referrerPolicy: {
policy: 'no-referrer',
},
}),
);
await app.listen(3000);
}
bootstrap();Не варто вимикати заголовок лише тому, що не відома його роль. Спочатку перевірте, який саме функціонал він блокує, і змініть лише потрібне налаштування.
Наприклад, повне вимкнення CSP:
app.use(
helmet({
contentSecurityPolicy: false,
}),
);може усунути проблему із завантаженням frontend-ресурсів, але водночас прибере важливий захисний механізм. Краще налаштувати конкретні джерела ресурсів, ніж вимикати CSP без необхідності.
Якщо NestJS-застосунок використовує Fastify, пакет helmet для Express не підходить. Для Fastify використовується адаптер @fastify/helmet.
Встановлення:
npm install @fastify/helmetПідключення має виглядати так:
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import helmet from '@fastify/helmet';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
// Реєструємо Helmet як плагін Fastify
await app.register(helmet);
await app.listen(3000, '0.0.0.0');
}
bootstrap();Спосіб підключення залежить від HTTP-адаптера:
Express — helmet і app.use(helmet());
Fastify — @fastify/helmet і app.register(helmet).
Після підключення Helmet:
Запустіть NestJS-застосунок.
Надішліть HTTP-запит до будь-якого маршруту.
Перегляньте заголовки відповіді через curl або вкладку Network у DevTools.
Переконайтеся, що заголовки не спричинили помилок у frontend.
Приклад перевірки:
curl -I http://localhost:3000/healthЯкщо маршрут /health існує, у відповіді мають бути заголовки безпеки, додані Helmet.
Для Express потрібно встановлювати helmet, а для Fastify — @fastify/helmet.
Не можна використовувати Express middleware як Fastify-плагін.
Helmet потрібно підключити до app.listen():
const app = await NestFactory.create(AppModule);
app.use(helmet());
await app.listen(3000);Так middleware буде застосовано до маршрутів застосунку.
CSP або HSTS іноді потребують налаштування. Це не означає, що потрібно вимикати весь Helmet:
// Небажано без крайньої потреби
app.use(helmet(false));Краще змінити конкретну опцію, яка створює проблему.
Якщо production працює через HTTP, не слід вмикати HSTS. Браузер може почати примусово перенаправляти запити на HTTPS, хоча HTTPS ще не налаштований.
Helmet не перевіряє права доступу, не шифрує паролі та не очищає дані користувача. Він лише налаштовує HTTP-заголовки.
Helmet автоматично додає до відповідей NestJS захисні HTTP-заголовки.
Для Express використовується пакет helmet.
Для Fastify використовується пакет @fastify/helmet.
Підключати Helmet потрібно під час створення застосунку, до app.listen().
CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy та HSTS зменшують типові вебризики.
HSTS слід застосовувати для production через HTTPS.
Якщо заголовок заважає роботі застосунку, краще налаштувати конкретну опцію, а не вимикати весь Helmet.