Как использовать helmet middleware для защиты Express приложения?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Helmet Middleware для Express
Helmet - это критически важный middleware для обеспечения безопасности Express приложений. Он устанавливает HTTP заголовки, которые защищают от известных веб-уязвимостей.
Установка и базовое использование
npm install helmet
const express = require("express");
const helmet = require("helmet");
const app = express();
// Применить все защиты по умолчанию
app.use(helmet());
app.get("/", (req, res) => {
res.send("Protected!");
});
app.listen(3000);
Одна строка app.use(helmet()) включает множество защит.
Что делает Helmet
Helmet устанавливает 15+ защитных заголовков:
# До helmet
curl -I http://localhost:3000
# HTTP/1.1 200 OK
# Content-Type: text/html
# После helmet
curl -I http://localhost:3000
# HTTP/1.1 200 OK
# Strict-Transport-Security: max-age=15552000; includeSubDomains
# X-Content-Type-Options: nosniff
# X-Frame-Options: DENY
# X-XSS-Protection: 0
# Content-Security-Policy: default-src 'self'
# ...(и ещё 10+ заголовков)
Основные защиты
1. Strict-Transport-Security (HSTS)
app.use(helmet.hsts({
maxAge: 31536000, // 1 год в секундах
includeSubDomains: true, // Применить к поддоменам
preload: true // Добавить в HSTS preload list
}));
Это заставляет браузер всегда использовать HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
2. Content Security Policy (CSP)
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"], // По умолчанию - только от себя
scriptSrc: ["'self'", "'unsafe-inline'"], // Скрипты
styleSrc: ["'self'", "https://fonts.googleapis.com"], // Стили
imgSrc: ["'self'", "data:", "https:"], // Изображения
connectSrc: ["'self'", "https://api.example.com"], // XHR/WebSocket
fontSrc: ["'self'", "https://fonts.gstatic.com"], // Шрифты
objectSrc: ["'none'"], // Запретить <object>, <embed>
mediaSrc: ["'self'"], // Видео/аудио
frameSrc: ["'none'"], // Запретить <iframe>
},
reportUri: "/csp-violation-report" // Отправлять ошибки сюда
}));
// Обработчик для отчётов о нарушениях CSP
app.post("/csp-violation-report", (req, res) => {
console.log("CSP Violation:", req.body);
res.status(204).send();
});
CSP защищает от XSS-атак, ограничивая, где браузер может загружать ресурсы.
3. X-Content-Type-Options (MIME Sniffing)
app.use(helmet.noSniff());
// или явно:
app.use(helmet.noSniff({
// Пусто - использует дефолт
}));
Отправляет заголовок:
X-Content-Type-Options: nosniff
Без этого браузер может неправильно интерпретировать тип файла (например, CSS как JS).
4. X-Frame-Options (Clickjacking защита)
app.use(helmet.frameguard({
action: "deny" // или 'sameorigin', 'allow-from'
}));
Отправляет:
X-Frame-Options: DENY
Это запрещает встраивать страницу в <iframe> другим сайтам (защита от clickjacking).
5. X-XSS-Protection
app.use(helmet.xssFilter());
Отправляет:
X-XSS-Protection: 0
Для современных браузеров это неактуально (используй CSP вместо этого), но для старых браузеров помогает.
6. Referrer Policy
app.use(helmet.referrerPolicy({
policy: "no-referrer" // или strict-no-referrer, same-origin, etc
}));
Отправляет:
Referrer-Policy: no-referrer
Контролирует, какую информацию о переходе отправлять.
7. Permissions Policy (ранее Feature Policy)
app.use(helmet.permissionsPolicy({
directives: {
geolocation: ["self"], // Геолокация только с того же оригина
microphone: [], // Микрофон запрещён
camera: [], // Камера запрещена
payment: ["self"], // Payment API только с того же оригина
}
}));
Отправляет:
Permissions-Policy: geolocation=(self), microphone=(), camera=()
Полный защищённый пример
const express = require("express");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
const mongoSanitize = require("express-mongo-sanitize");
const xss = require("xss-clean");
const app = express();
// 1. Helmet - заголовки безопасности
app.use(helmet());
// 2. Кастомизированная CSP для приложения
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: [
"'self'",
"https://cdn.jsdelivr.net", // Для CDN бибилиотек
"https://code.jquery.com"
],
styleSrc: ["'self'", "'unsafe-inline'"], // Inline стили (если нужны)
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "https://api.example.com"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
objectSrc: ["'none'"],
frameSrc: ["'none'"],
reportUri: "/csp-violation-report"
}
}));
// 3. Защита от MIME sniffing
app.use(helmet.noSniff());
// 4. Защита от clickjacking
app.use(helmet.frameguard({ action: "deny" }));
// 5. HSTS для HTTPS
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
// 6. Permissions Policy
app.use(helmet.permissionsPolicy({
directives: {
geolocation: ["self"],
microphone: [],
camera: []
}
}));
// 7. Защита от DoS атак
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: 100 // максимум 100 запросов за окно
});
app.use(limiter);
// 8. Парсирование JSON
app.use(express.json());
// 9. Защита от NoSQL injection
app.use(mongoSanitize({
replaceWith: "_",
onSanitize: ({ req, key }) => {
console.warn(`Sanitized key: ${key}`);
}
}));
// 10. Защита от XSS (дополнительно к CSP)
app.use(xss());
// 11. Отключить header X-Powered-By (не раскрывай технологический стек)
app.disable("x-powered-by");
// 12. CORS - если нужно
const cors = require("cors");
app.use(cors({
origin: "https://example.com", // Только доверенные источники
credentials: true, // Разрешить cookies
optionsSuccessStatus: 200
}));
// Обработчик для CSP отчётов
app.post("/csp-violation-report", (req, res) => {
const violation = req.body["csp-report"];
console.error("CSP Violation:", {
blockedUri: violation["blocked-uri"],
violatedDirective: violation["violated-directive"],
originalPolicy: violation["original-policy"],
sourceFile: violation["source-file"],
lineNumber: violation["line-number"]
});
res.status(204).send();
});
app.get("/", (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Protected App</title>
<style>body { font-family: Arial; }</style>
</head>
<body>
<h1>Secure Express App</h1>
<p>Защищено с помощью Helmet!</p>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log("Server running on https://localhost:3000");
});
Проверка заголовков
# Посмотреть все заголовки безопасности
curl -I https://localhost:3000 | grep -E "(Strict-Transport|Content-Security|X-|Referrer|Permissions)"
# Или используй онлайн инструмент
# https://securityheaders.com/
Конфигурирование для разных окружений
const helmet = require("helmet");
if (process.env.NODE_ENV === "production") {
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "https:"],
upgradeInsecureRequests: true // Автоматически HTTPS
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
} else {
// Development - менее строгие правила для отладки
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"]
}
}
}));
}
Best Practices
- Всегда используй Helmet - это первая строка защиты
- Настраивай CSP под свои нужды - слишком строгая политика сломает функциональность
- Используй HTTPS - Helmet защищает только при HTTPS
- Сочетай с другими middleware - rate limiting, input validation, CORS
- Мониторь CSP отчёты - они помогут найти уязвимости
- Тестируй на securityheaders.com - проверь оценку своего приложения
- Регулярно обновляй Helmet - уязвимости в заголовках находят постоянно
Helmet - это не серебряная пуля, но обязательный фундамент безопасности любого Express приложения.