HTTP-заголовки безопасности
HTTP security-заголовки — это инструкции, которые сервер отправляет браузеру вместе с ответом. Они не требуют изменений в бизнес-логике, но закрывают целые классы атак: HSTS блокирует downgrade на HTTP, X-Frame-Options — clickjacking, Referrer-Policy — утечку URL, COOP/COEP — cross-origin атаки. Статья систематизирует основные заголовки, их значения и способы настройки в Next.js и Nuxt.
Содержание
- Почему заголовки — это важно
- Content-Security-Policy
- Strict-Transport-Security (HSTS)
- X-Frame-Options
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
- Cross-Origin-Opener-Policy (COOP)
- Cross-Origin-Embedder-Policy (COEP)
- Cross-Origin-Resource-Policy (CORP)
- Clear-Site-Data
- Cache-Control для чувствительных страниц
- Как настроить в Next.js и Nuxt
- Чек-лист заголовков
- Терминология
- Ключевые тезисы для интервью
- Заключение
- Полезные ссылки
Почему заголовки — это важно
HTTP-заголовки безопасности — это инструкции, которые сервер отправляет браузеру вместе с ответом. Они не требуют изменений в бизнес-логике приложения, но эффективно закрывают целые классы атак.
Аналогия: если HTML-страница — это содержимое письма, то security-заголовки — это конверт с пометками: «Не вскрывать», «Только лично в руки», «Вернуть отправителю при нарушении». Браузер читает эти пометки и ведёт себя соответственно.
Content-Security-Policy
Подробно разобран в отдельной статье CSP: глубокое погружение.
Кратко: CSP говорит браузеру, откуда разрешено загружать скрипты, стили, изображения и другие ресурсы. Это вторая линия обороны от XSS.
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
Strict-Transport-Security (HSTS)
HSTS указывает браузеру, что сайт должен загружаться только по HTTPS. Даже если пользователь введёт http://example.com, браузер автоматически перенаправит на HTTPS.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age— время в секундах, на которое браузер запоминает политику.includeSubDomains— распространяет политику на поддомены.preload— позволяет включить сайт в preload-список браузеров.
Предостережение
Перед включением HSTS убедитесь, что весь сайт работает по HTTPS. Иначе пользователи не смогут зайти.
X-Frame-Options
Запрещает встраивание страницы в <iframe>. Защищает от clickjacking — атаки, при которой злоумышленник накладывает прозрачный iframe с вашим сайтом на свою страницу.
X-Frame-Options: DENY
Возможные значения:
DENY— запретить встраивание полностью.SAMEORIGIN— разрешить встраивание только с того же источника.
Современная альтернатива — директива CSP frame-ancestors:
Content-Security-Policy: frame-ancestors 'none'
X-Content-Type-Options
Запрещает браузеру угадывать MIME-тип файла (mime sniffing). Без этого заголовка браузер может интерпретировать, например, загруженный .txt как JavaScript.
X-Content-Type-Options: nosniff
Referrer-Policy
Контролирует, какой URL отправляется в заголовке Referer при переходе на другие сайты.
Referrer-Policy: strict-origin-when-cross-origin
| Значение | Поведение |
|---|---|
no-referrer | Не отправлять Referer вообще |
strict-origin-when-cross-origin | На своём сайте — полный URL, на чужом — только origin |
origin | Всегда отправлять только origin |
unsafe-url | Всегда отправлять полный URL (небезопасно) |
Рекомендуется strict-origin-when-cross-origin — баланс приватности и функциональности.
Permissions-Policy
Контролирует, какие браузерные API могут использоваться на странице.
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Если ваше приложение не использует камеру — заблокируйте её. Это уменьшает поверхность атаки и защищает приватность пользователей.
Cross-Origin-Opener-Policy (COOP)
COOP изолирует окно/вкладку от других источников. Защищает от атак через window.opener, таких как tabnabbing.
Cross-Origin-Opener-Policy: same-origin
| Значение | Поведение |
|---|---|
same-origin | Только окна с того же origin могут взаимодействовать |
same-origin-allow-popups | Разрешить взаимодействие с попапами того же origin |
unsafe-none | Нет изоляции (по умолчанию) |
Cross-Origin-Embedder-Policy (COEP)
COEP требует, чтобы встроенные ресурсы (iframe, изображения, скрипты) разрешали cross-origin embedding через CORP или CORS.
Cross-Origin-Embedder-Policy: require-corp
Вместе с COOP включает так называемый cross-origin isolated режим, который необходим для некоторых мощных API (SharedArrayBuffer, performance.measureUserAgentSpecificMemory и др.).
Cross-Origin-Resource-Policy (CORP)
CORP указывает, кто может встраивать ваши ресурсы на других сайтах.
Cross-Origin-Resource-Policy: same-origin
| Значение | Поведение |
|---|---|
same-origin | Только ваш origin |
same-site | Тот же site (включая поддомены) |
cross-origin | Любой origin |
Clear-Site-Data
Позволяет серверу приказать браузеру очистить cookie, storage, cache. Полезен при logout.
Clear-Site-Data: "cookies", "storage", "cache"
При выходе из системы это гарантирует, что браузер удалит сессионные данные.
Cache-Control для чувствительных страниц
Не security-заголовок в узком смысле, но важен для защиты данных.
Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate
Pragma: no-cache
Expires: 0
Используйте для страниц с личными данными, чтобы браузер и прокси не кэшировали их.
Как настроить в Next.js и Nuxt
Next.js
// next.config.js
const securityHeaders = [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
{ key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
];
module.exports = {
async headers() {
return [{ source: '/(.*)', headers: securityHeaders }];
},
};
Nuxt
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-security'],
security: {
headers: {
xFrameOptions: 'DENY',
xContentTypeOptions: 'nosniff',
referrerPolicy: 'strict-origin-when-cross-origin',
permissionsPolicy: 'camera=(), microphone=(), geolocation=()',
strictTransportSecurity: {
maxAge: 31536000,
includeSubdomains: true,
},
crossOriginOpenerPolicy: 'same-origin',
},
},
});
Чек-лист заголовков
-
Content-Security-Policyнастроена и протестирована. -
Strict-Transport-Securityвключён для HTTPS-only сайтов. -
X-Frame-Optionsилиframe-ancestors 'none'защищают от clickjacking. -
X-Content-Type-Options: nosniffустановлен. -
Referrer-Policyограничивает утечку URL. -
Permissions-Policyблокирует ненужные API. -
Cross-Origin-Opener-Policyвключён. - Для чувствительных страниц
Cache-Control: no-store. - При logout используется
Clear-Site-Data.
Терминология
| Термин | Значение |
|---|---|
| HSTS | HTTP Strict Transport Security — принудительный HTTPS |
| CSP | Content Security Policy |
| COOP | Cross-Origin-Opener-Policy — изоляция окон |
| COEP | Cross-Origin-Embedder-Policy — требования к встраиваемым ресурсам |
| CORP | Cross-Origin-Resource-Policy — политика встраивания ресурсов |
| Clickjacking | Атака через прозрачный iframe |
| Tabnabbing | Атака через window.opener открытой вкладки |
| Mime sniffing | Определение MIME-типа браузером по содержимому |
| Cross-origin isolated | Режим с COOP + COEP для мощных API |
Ключевые тезисы для интервью
- Security-заголовки — самый дешёвый слой защиты: только конфигурация, никаких изменений в коде; HSTS (
Strict-Transport-Security) заставляет браузер использовать HTTPS,X-Content-Type-Options: nosniffзапрещает угадывать MIME-тип. X-Frame-Options: DENYи CSPframe-ancestors 'none'защищают от clickjacking; современный подход —frame-ancestorsв CSP.Referrer-Policy: strict-origin-when-cross-origin— баланс приватности и функциональности;Permissions-Policyблокирует ненужные API (камера, микрофон, геолокация), уменьшая поверхность атаки.- COOP + COEP включают cross-origin isolated режим, необходимый для SharedArrayBuffer; COOP защищает от tabnabbing и атак через
window.opener. Clear-Site-Dataпри logout удаляет cookies, storage и cache — критично для общих устройств;Cache-Control: no-storeдля чувствительных страниц предотвращает кэширование в браузере и прокси.- Все заголовки настраиваются в Next.js middleware и Nuxt server routes; для SOC2/CASA наличие и документирование — стандартный evidence.
Заключение
Security-заголовки — это дешёвый и эффективный способ защиты. Они не заменяют безопасный код, но добавляют несколько независимых слоёв защиты: HSTS против downgrade, frame-ancestors против clickjacking, nosniff против mime sniffing, COOP/COEP против cross-origin атак. Для SOC2 и CASA наличие и документирование этих заголовков — стандартный evidence. Фронтенд-разработчик должен знать, какой заголовок за что отвечает, и уметь настраивать их в своём фреймворке.