Проверка HTTP-заголовков безопасности

Что делает каждый заголовок, что на самом деле отдаёт ваш сайт и какую строку добавить. Без буквенных оценок.

С чего начать, если вы только начинаете

Заголовки не равноценны и не одинаково рискованны при внедрении. Вот порядок, дающий больше всего защиты при наименьшем шансе что-нибудь сломать:

ЗаголовокОстанавливаетРиск что-то сломать
Strict-Transport-SecurityПонижение HTTPS при первом визитеНет, если вы уже отдаёте только по HTTPS
X-Content-Type-OptionsУгадывание MIME-типа загруженных файловНа практике нет
Referrer-PolicyУтечку URL третьим сторонамНизкий — может повлиять на атрибуцию в аналитике
X-Frame-Options / frame-ancestorsКликджекингНизкий, если только вас кто-то законно не встраивает
Permissions-PolicyЗапрос камеры или геопозиции встроенными фреймамиНизкий
Content-Security-PolicyИсполнение внедрённого скриптаВысокий. Сначала режим только отчётов.

Последняя строка — самая важная и единственная, требующая настоящей работы. Всё, что выше неё, — это один вечер.

HSTS и одно необратимое решение внутри него

Strict-Transport-Security велит браузеру использовать для этого узла HTTPS в течение следующих max-age секунд, что бы ни случилось. Он закрывает узкую, но реальную щель: посетитель, набравший example.com, делает один незашифрованный запрос до вашего перенаправления, и этот запрос можно перехватить.

Strict-Transport-Security: max-age=31536000; includeSubDomains

includeSubDomains важнее, чем кажется. Без него поддомен, отдаваемый по HTTP, всё ещё может ставить куки для родительского домена. С ним каждый поддомен обязан работать только по HTTPS, иначе становится недоступным, — так что проверьте, прежде чем добавлять.

Директива preload — вот над чем стоит крепко подумать. Она вписывает ваш домен в списки предзагрузки, поставляемые вместе с браузерами, так что HTTPS принуждается ещё до первого запроса. Она же практически необратима: удаление требует заявки сопровождающим списка и затем ожидания, пока разойдутся релизы браузеров, — это месяцы. Отлично, когда вы уверены; и плохая идея, чтобы добавлять между делом.

CSP: режим только отчётов не опция

Content-Security-Policy — единственный здесь заголовок, останавливающий выполнение внедрённого скрипта, и единственный, способный уронить ваш сайт. Оба факта следуют из одного свойства: он ограничивает то, что вообще может загружаться.

Разверните его в режиме только отчётов со сборщиком и оставьте на несколько недель настоящего трафика. Обнаружится не то, что вы ожидали, читая код: найдётся забытый хост шрифтов, платёжный iframe и нередко скрипт, подмешанный на границе CDN, которого нет ни в одном исходном файле. Именно последняя категория и есть то, ради чего существует режим отчётов.

Content-Security-Policy-Report-Only: default-src 'self';
  script-src 'self'; object-src 'none'; base-uri 'self';
  report-uri /csp-report

Две вещи сводят на нет большую часть пользы. 'unsafe-inline' в script-src разрешает ровно тот внедрённый встроенный скрипт, ради остановки которого политика и существует, — выход в nonce или хешах. А 'unsafe-eval' возвращает eval и его родню, которые всё ещё нужны некоторым старым сборкам фреймворков. Проверщик отмечает оба как ослабление, а не как отсутствие, потому что политика с ними всё ещё делает полезную работу — просто не главную.

Заголовки, чьи рекомендации истекли

  • `X-XSS-Protection` — управлял браузерным фильтром, удалённым из всех основных браузеров, и тот в своё время сам поддавался манипуляциям, ломавшим страницы. В 2026 году это не тот заголовок, который стоит выставлять.
  • `Expect-CT` — устарел. Certificate Transparency теперь применяется безусловно, так что заголовок не делает ничего.
  • `Feature-Policy` — переименован в Permissions-Policy, с другим синтаксисом. Учитывается только новое имя.
  • `Public-Key-Pins` — удалён из браузеров, и правильно. Ошибка в нём выводила ваш домен из строя на весь срок закрепления без всякой возможности восстановиться.

Чего эта проверка не делает

Одна страница, один ответ. Она читает заголовки итогового ответа после всех перенаправлений и на этом останавливается. Она не обходит сайт, не выполняет JavaScript, не проверяет вашу конфигурацию TLS и не смотрит флаги кук, — а разные пути одного сайта могут отдавать совершенно разные заголовки, так что проверка главной страницы рассказывает о главной странице.

Что до конфигурации TLS, признанный и дотошный инструмент — Qualys SSL Labs. А сам сертификат читает этот: он показывает, что узел предъявляет на самом деле.

Вопросы о заголовках

Почему здесь нет оценки или буквенного рейтинга?

Потому что оценка — единственный результат, с которым нечего делать. Узнав, что у вас «C», вы не узнаёте, какого заголовка не хватает, чем он важен именно для вашего сайта и что в нём выставить, — зато появляется соблазн добавлять заголовки ради буквы, а не ради решения проблемы. Сайт со строгой CSP и без Permissions-Policy в куда лучшей форме, чем сайт с шестью заголовками, выставленными в разрешительные значения, и никакая буква этого не выразит. Поэтому здесь каждый заголовок разбирается отдельно, оценивается то значение, которое вы действительно отдаёте, и выдаётся готовая строка.

Какой заголовок добавить первым?

Strict-Transport-Security, если вы уже работаете только по HTTPS. Это одна строка, она не сломает ничего работавшего и закрывает окно понижения протокола при первом визите. Затем Content-Security-Policy в режиме только отчётов — вот у неё настоящие зубы, а режим отчётов позволяет выяснить, что сайт на самом деле загружает, прежде чем что-то принуждать. X-Content-Type-Options: nosniff тоже ничего не стоит и просто должен быть включён.

Не сломает ли Content-Security-Policy мой сайт?

Легко может, для того и существует режим только отчётов. Разверните Content-Security-Policy-Report-Only со сборщиком, оставьте на пару недель настоящего трафика и прочитайте, что он сообщает: обнаружатся ресурсы, о которых вы забыли, и нередко то, что подмешивает на границе CDN или поставщик аналитики и чего нет ни в одном исходном файле. Принуждать стоит только тогда, когда отчёты стихли. Политика, написанная по прочтении кодовой базы и включённая сразу, — это классический способ уронить оформление заказа.

Стоит ли выставлять X-XSS-Protection?

Нет. Он управлял браузерным XSS-фильтром, который удалён из всех основных браузеров — Chrome отказался от него в 2019 году, — а в своё время сам фильтр порождал уязвимости, поскольку им можно было манипулировать, ломая страницы, которые уязвимы не были. Выставить 0 допустимо, если какой-нибудь сканер настаивает; выставлять 1; mode=block — значит повторять совет, истёкший много лет назад. Заменой служит Content-Security-Policy.

Нужен ли X-Frame-Options, если есть CSP?

Нет, при условии что ваша CSP задаёт frame-ancestors, которая во всех современных браузерах его замещает. Этот инструмент учитывает это и не сообщает об отсутствии X-Frame-Options, когда работу делает frame-ancestors. Держать оба ничего не стоит, но помогает лишь в браузерах настолько старых, что у вас, вероятно, есть заботы посерьёзнее.

Отсутствие заголовка означает, что я уязвим?

Нет. Заголовки безопасности — это эшелонированная защита: они ограничивают ущерб от уязвимости, но не создают и не устраняют её. Сайт без CSP не уязвим к XSS; уязвим сайт с ошибкой XSS, а CSP не даёт этой ошибке перерасти в полную компрометацию. Добавлять заголовки полезно и дёшево, но это не замена экранированию вывода, проверке ввода и поддержанию зависимостей в актуальном состоянии.

Последняя проверка . Заметили, что что-то устарело? Напишите нам.