14 янв. 2026 г.·7 мин. чтения

Защищённые загрузки файлов с подписанными URL: практическая настройка

Защищённые загрузки через подписанные URL: предотвращайте path traversal, принудительно задавайте безопасные типы содержимого и делайте ссылки с истечением, чтобы приватные файлы оставались приватными.

Защищённые загрузки файлов с подписанными URL: практическая настройка

Почему приватные загрузки случайно становятся публичными

Большинство «приватных загрузок» начинаются просто: положили файл на сервер, добавили роут вроде /download?file=... и полагаетесь на то, что кнопку увидят только залогиненные. Проблема в том, что файлы скачивают не с кнопки — а с адреса, который можно скопировать, переслать, угадать или опросить скриптом.

Распространённая ошибка — отдавать приватный файл так же, как публичную страницу. Если URL для скачивания работает при каждом запросе без строгих проверок, не важно, где он был показан. Любой может вызвать эндпойнт напрямую, и приложение может вернуть файл.

«Скрытые URL» — не защита. Случайные имена файлов и длинные пути лишь замедляют простое угадывание. Они не предотвращают:

  • Пользователя, пересылающего ссылку другому
  • Историю браузера, логи, скриншоты или тикеты поддержки, через которые URL может утечь
  • Ботов, сканирующих предсказуемые шаблоны (например, /uploads/ или /invoices/)
  • Баг, который даёт листинг директории или позволяет ../ трюки

Эндпойнты скачивания привлекательны для атакующих, потому что часто касаются чувствительных данных (счета, контракты, выгрузки) и их легко тестировать: шлёшь запросы, смотришь ответ, повторяешь. Если эндпойнт принимает имя файла из запроса, атакующий может пробовать файлы других пользователей или path traversal, чтобы выйти из нужной папки.

Подписанные URL меняют правила: URL сам по себе несёт доказательство того, что он выдан вашим сервером для конкретной цели. Правильный подписанный URL обычно связывает, какой файл разрешён, какие права применяются (иногда через пользователя или организацию) и как долго ссылка действительна.

Подписанные URL не чудо. Они не исправят сломанную модель авторизации и не помогут, если сервер подписывает «любой путь, который просит пользователь». Они также не помешают кому‑то переслать ссылку, пока она валидна.

Простой пример: сотрудник поддержки копирует URL скачивания счёта из админки и вставляет его в чат. Если URL просто «выглядит секретно», он может работать долго и превратиться в постоянный публичный эндпойнт. Если это подписанная ссылка с истечением, привязанная к конкретному счёту, её сложнее злоупотребить, и она перестанет работать через короткое окно.

Подписанные URL без жаргона

Подписанный URL — это обычная ссылка загрузки с дополнительным «доказательством». Доказательство — подпись: короткая строка, которую ваш сервер создаёт с помощью секретного ключа, известного только серверу.

Когда кто‑то кликает ссылку, сервер может сказать, была ли она выдана вашим приложением или её подделали. Это и есть суть.

Что именно подписывают?

Подпись вычисляют по нескольким конкретным значениям, объединяют в одно сообщение и «запечатывают» вашим секретом. Типичный подписанный URL для скачивания включает:

  • Идентификатор файла (не сырый путь в файловой системе)
  • Время истечения (метка времени)
  • Опциональный контекст: ID пользователя, ID арендатора или действие (download)
  • Иногда HTTP‑метод (GET), чтобы подпись нельзя было переиспользовать для других запросов

Если что‑то из этого меняется, подпись перестаёт соответствовать.

Время жизни важно, потому что ссылки текут: их пересылают, история браузера их хранит, логи фиксируют, делают скриншоты. Временные ссылки ограничивают радиус ущерба, когда утечка неизбежна.

Что сервер проверяет перед отправкой файла

Когда приходит запрос, сервер повторяет ту же операцию подписи по значениям из запроса. Если вычисленная подпись совпадает с той, что в URL, и метка времени ещё не истекла, запрос проходит первый фильтр.

После этого сервер всё равно применяет реальные проверки прав. Если Алиса кликает ссылку на счёт Боба, подпись может быть валидной, но Алисе всё равно должно вернуться «не разрешено», потому что файл ей не принадлежит.

Подписанные URL встречаются в нескольких вариантах:

  • Параметры Query (просто и распространено)
  • Заголовки Authorization (чистые URL, сложнее пересылать)
  • Cookies (удобно для загрузок в браузере без токенов в URL)

Типичная ошибка в прототипах — реализовать подпись «впол‑силы» (проверка подписи только, без проверки владения). Так приватные файлы становятся публичными, как только формат URL обнаружен.

Предотвращайте path traversal: никогда не доверяйте путям файлов

Path traversal случается, когда приложение даёт пользователю влияние на путь к файлу, и пользователь использует это, чтобы добраться до файлов, которые он не должен видеть. Классический пример — ../ (вверх по папкам), но атакующие редко останавливаются на этом. Они пробуют URL‑кодированные версии вроде %2e%2e%2f, двойное кодирование, обратные слэши (..\\\\) для Windows или странные разделители, которые ОС нормализует позже.

Поэтому опасно, когда эндпойнт скачивания принимает что‑то вроде ?file=reports/2025/invoice.pdf. Даже проверка на ../ может подвести из‑за порядка декодирования (декодировать один раз против двух), смешанных слэшей или фреймворка, который нормализует путь уже после валидации.

Безопасный паттерн прост: пользователи никогда не передают путь. Они дают непрозрачный ID (или подписанный токен), а сервер смотрит реальное местоположение в хранилище.

Пример: вместо GET /download?file=... используйте GET /download?docId=8f31.... На сервере берёте docId из базы, подтверждаете, что запрашивающий может получить доступ, затем читаете точный сохранённый путь (или ключ объекта), который вы сами создали. У пользователя нет шанса «нацелить» ваш вызов чтения файла.

Если работать с путями всё же нужно (например, локальное диск‑хранилище), нормализуйте и валидируйте до доступа к файлу. Хорошее правило: строьте итоговый путь из известной базовой директории плюс безопасное относительное имя, затем подтвердите, что после нормализации он остаётся внутри базы.

Практические проверки, которые надёжнее простых фильтров строк:

  • Отклоняйте абсолютные пути (начинающиеся с /, \\\\ или с префикса диска вроде C:).
  • Декодируйте один раз, нормализуйте, затем валидируйте. Не валидируйте «сырую» строку.
  • Блокируйте неожиданные разделители (смешение / и \\\\) и нулевые байты.
  • После объединения base + requested убедитесь, что нормализованный путь начинается с нормализованной базы.
  • Предпочитайте allowlist известных ключей файлов из базы данных, а не любое имя файла от пользователя.

Многие сломанные обработчики скачивания ошибаются, потому что концентрируются на части с подписанным URL и забывают, что путь всё ещё может контролироваться атакующим.

Принудительно устанавливайте типы контента, чтобы файлы не запускались как страницы

Подписанные URL контролируют, кто может получить файл. Они не управляют тем, как браузер воспринимает файл после получения. Если вы отдаёте загруженный файл с неправильными заголовками, «скачивание» может превратиться в страницу, которая выполнится в сессии пользователя.

Частая неожиданность — content type sniffing. Даже если вы шлёте общий тип, некоторые браузеры пытаются угадать тип содержимого. Если контент похож на HTML или JavaScript, браузер может отрендерить его вместо скачивания. Так безобидная загрузка превращается в выполняющийся скрипт.

Всегда ставьте правильные заголовки

Сделайте эндпойнт скачивания единственным местом, где задаются заголовки. Не полагайтесь на то, что слой хранения «знает» тип.

Минимум, что нужно установить в ответе:

  • Content-Type: разрешайте только ожидаемые типы (например, application/pdf, image/png).
  • Content-Disposition: attachment; filename=\"...\": принуждает скачивание вместо inline‑рендеринга.
  • X-Content-Type-Options: nosniff: просит браузер не угадывать.

Также рассматривайте имя файла как недоверенный ввод. Если вы формируете filename из данных пользователя, уберите разделители путей и управляющие символы. Оставьте простые символы: буквы, цифры, точки, дефисы, подчёркивания. Если нужен «красивый» имя‑файл, храните его отдельно от ключа в хранилище.

Блокируйте рискованные типы и используйте безопасный шаблон по умолчанию

Если пользователи могут загружать файлы, решите, что вы никогда не будете отдавать в исходном виде. HTML, SVG и всё, связанное со скриптами — высокий риск, потому что может выполниться в браузере.

Простая политика, которая часто работает:

  • Разрешите узкий список известных типов (PDF, распространённые изображения, CSV при необходимости).
  • Отклоняйте или помещайте в карантин text/html, image/svg+xml и любые типы, связанные с JavaScript.
  • Если тип файла отсутствует или не входит в allowlist, отдавайте application/octet-stream.
  • Всегда используйте Content-Disposition: attachment для файлов, загруженных пользователями.

Конкретный пример: если кто‑то загрузил invoice.html, а вы отдали его с Content-Type: text/html и inline‑показом, открытие ссылки может запустить скрипты. Если вы принудите application/octet-stream и attachment, тот же файл станет безопасным скачиванием.

Как безопасно подписывать и проверять URL

Check your downloads now
We will review your download routes for auth gaps, traversal risk, and unsafe headers.

Подписанный URL безопасен ровно настолько, насколько правильно вы подписываете и строго проверяете его. Цель проста: сервер должен доказать, что запрос разрешён для конкретного файла, на ограниченное время и (если нужно) для конкретного пользователя, не доверяя тому, что прислал браузер.

Безопасный паттерн подписи

Держите секрет подписи только на сервере. Не отправляйте его клиенту, не помещайте в переменные окружения, доступные сборке для браузера, и никогда не включайте в URL. URL должен нести только публичные данные плюс подпись.

Подписывайте небольшой жёсткий набор полей и считайте всё остальное недоверенным. Практический минимальный набор:

  • rid: идентификатор ресурса (не путь к файлу)
  • exp: метка истечения
  • sub: ID пользователя или арендатора, когда скачивания связаны с пользователем
  • sig: подпись (например, HMAC)

На сервере создайте каноническую строку в фиксированном порядке (например rid=...\u0026exp=...\u0026sub=...). Затем подпишите эту строку. При проверке восстановите каноническую строку из распарсенных значений, пересчитайте подпись и сравните.

Используйте сравнение с постоянным временем для проверки подписи. Обычное сравнение строк может дать крошечные временные различия, которые помогают атакующим подбирать подпись через множество запросов.

Будьте строги при парсинге. Если поле отсутствует, дублировано, имеет неверный формат или выходит за допустимые пределы — отклоняйте. Также отвергайте любые дополнительные параметры, которые вы не подписывали. Иначе кто‑то может добавить \u0026role=admin или \u0026download=true и обмануть код, читающий эти значения.

Ниже — общая форма логики валидации (язык не важен):

allowed = {rid, exp, sub, sig, kid}
if any query key not in allowed: reject
parse rid, exp, sub (strict types)
if now \u003e exp: reject
canonical = \"rid=...\u0026exp=...\u0026sub=...\"
expected = HMAC(secret_for(kid), canonical)
if !constant_time_equals(sig, expected): reject
serve file for rid (after authz check)

Наконец, планируйте ротацию ключей. Добавьте небольшой kid (идентификатор ключа), чтобы можно было держать старый ключ доступным кратко, пока новые ссылки подписываются новым ключом. Старые ссылки всё равно должны быстро истекать, так что поддерживать старые ключи долго не придётся.

Сроки действия ссылок и правила доступа, которые действительно работают

Подписанный URL с истечением полезен только если срок соответствует задаче. Слишком короткий — получите тикеты в саппорт. Слишком длинный — тихая лазейка: «приватный» файл остаётся шарируемым днями.

Простое правило: ставьте срок как можно короче, при этом достаточный для задачи. Просмотр документа сейчас — 5–15 минут. Скачивание большого экспорта — 30–60 минут. Если действие можно возобновить позже, генерируйте новую ссылку после повторной аутентификации.

Одноразовые и многократные ссылки

Одноразовые ссылки снижают риск пересылки, но могут ломать реальные сценарии (смена приложений на мобильном, плохой Wi‑Fi, менеджеры загрузок, которые повторяют запросы). Многократные ссылки удобнее, но требуют жёстких ограничений.

Практические опции, которые обычно работают:

  • Короткоживущая многократная ссылка для обычных загрузок.
  • Одноразовая ссылка для очень чувствительных файлов (зарплата, приватные ключи, юридические документы).
  • Многократная ссылка с лимитом скачиваний (например, максимум 3 успешных скачивания).
  • Многократная ссылка, привязанная к пользователю или организации (подпись включает userId/orgId и fileId).
  • Многократная ссылка, привязанная к сессии, если нужно поведение «обязательно залогинен».

Чтобы уменьшить злоупотребления, добавьте rate limiting на эндпойнт валидации подписи. Даже подписанная ссылка может быть атакована. Ограничьте запросы по IP и по пользователю, рассматривайте блокировку после повторных неудач (плохие подписи, просроченные метки).

Логи важны для аудита, но держите их минимальными. Храните fileId, userId/orgId, метку времени и результат (success/denied). Избегайте логирования полного URL или строки запроса, так как там может быть подпись.

Пример: приложение по выставлению счетов может выдавать 15‑минутную подписанную ссылку для PDF‑счёта, привязанную к orgId клиента. Если ссылка утекает к поставщику, она не сработает, потому что orgId не совпадёт. Если пользователю нужна ссылка завтра — он запросит новую после входа.

Пошагово: постройте безопасный поток скачивания

Audit your AI generated code
Find hidden issues like exposed secrets, weak auth, and risky download handlers.

Держите файлы приватными по умолчанию. Храните их в месте, которое не отдаётся напрямую вашим веб‑сервером или CDN как публичная папка. Рассматривайте скачивание как действие, выполняемое вашим приложением, а не как статический файл, который любой может угадать.

Вот простой поток, который выдерживает реальные приложения:

  1. Храните файлы приватно, с ID: сохраняйте каждый файл с случайным внутренним ключом (или ID в базе), а не с именем, которое дал пользователь вроде ../../secret.env. Оригинальное имя храните только как метаданные для отображения.
  2. Пользователь запрашивает скачивание: он вызывает эндпойнт вроде GET /downloads/:fileId будучи залогиненным.
  3. Сначала проверяйте права: найдите запись файла и подтвердите, что текущий пользователь может получить доступ (владелец, член команды, оплаченный план и т. п.).
  4. Создайте короткоживущую подписанную ссылку: сгенерируйте URL, который включает fileId, метку истечения и подпись (HMAC). Делайте срок в минутах, а не в днях.
  5. Редирект или верните подписанную ссылку: клиент затем запрашивает подписанную ссылку, чтобы получить байты.

Когда эндпойнт подписанного URL получает запрос, будьте строги до того, как тронете данные файла. Сначала проверьте подпись и срок. Затем загрузите файл по внутреннему ключу, никогда по пути, присланному клиентом. В конце стримьте файл пользователю, чтобы большие загрузки не заполняли память сервера.

Хороший ответ на скачивание также ставит безопасные заголовки. Принуждайте скачивание через Content-Disposition: attachment и задавайте Content-Type из доверенных метаданных (или с помощью серверного детектирования). Не отражайте тип, присланный пользователем — так «скачивание» превращается в страницу, которая выполняется в браузере.

Для ошибок давайте полезные, но не избыточные сообщения. Пишите «Не найдено» или «Ссылка истекла», но не включайте внутренние пути, имена бакетов или трассировки стека.

Распространённые ошибки, которые дают ложное чувство безопасности

Подписанные URL могут быть очень безопасны, но только если вы рассматриваете их как часть общей проверки доступа. Большинство провалов происходит, когда подпись верна, но сервер всё равно выдаёт неправильный файл или отдаёт его небезопасно.

Одна ловушка — подписывать «полную строку URL» точно так, как она выглядит в браузере. Небольшие изменения могут ломать проверку или создавать обходы: порядок параметров может меняться, пробелы кодироваться по‑разному или прокси может добавлять параметр. Если код подписывает одну версию, а проверяет другую, вы получите нестабильность и временные «обходы», которые ослабляют безопасность.

Ещё одна частая ошибка — позволять пользователю контролировать путь или расширение файла. Даже с валидной подписью вы не хотите видеть ../ трюки, неожиданные юникод‑символы или .html‑загрузки. Подписанный URL должен указывать на стабильный идентификатор файла (вроде внутреннего ID), а сервер должен решать, где реально хранится файл.

Провал в истечении срока тоже популярен. Команды генерируют «временные» ссылки на недели или забывают проверять метку вообще. Тогда «приватный» файл превращается в долгоживущий публичный эндпойнт, который можно пересылать, индексировать или снимать сканерами.

Наконец, многие забывают, что скачивания — это ещё поверхность доставки контента. Если вы отдаёте пользовательские загрузки как text/html (или позволяете браузеру угадывать), загруженный файл может выполниться как страница. Это может привести к захватам аккаунтов через внедрение скрипта, даже если URL был подписан.

Красные флаги, на которые стоит обратить внимание

  • Подписи зависят от точного порядка параметров или кодирования URL.
  • Пользователь может запросить произвольный путь, имя файла или расширение.
  • Отсутствует истечение, оно не проверяется или стоит слишком далеко в будущем.
  • Ответы позволяют content sniffing или возвращают неправильный Content-Type.
  • Секреты подписи попадают в клиентский код, логи или подробные сообщения об ошибках.

Пример: защита скачиваний счетов и документов

Stop private files going public
If your AI-built app leaks files, we can diagnose and repair the access model.

Представьте портал клиентов, где у каждого аккаунта есть счета (PDF) и документы для верификации (изображения или PDF). Эти файлы приватны, но пользователям нужен простой «Скачать».

Типичная ошибка — портал генерирует постоянный URL вроде /files/1234/invoice.pdf. Кто‑то пересылает его в групповом чате, и теперь любой с этой ссылкой может получить файл. Ещё хуже, поисковики и лог‑системы могут сохранить такой URL, превращая приватный документ в полу‑публичный.

С подписанными, истекающими ссылками портал не показывает стабильный, угадываемый адрес. Вместо этого выдаётся короткоживущая ссылка, привязанная к конкретному файлу и (по необходимости) к пользователю или организации.

Практический поток выглядит так:

  • Пользователь кликает «Скачать счёт» будучи залогинен.
  • Сервер проверяет: принадлежит ли этот пользователь счёту inv_9281?
  • Сервер генерирует подписанную ссылку с user_id, file_id и временем истечения.
  • Эндпойнт проверки подписи убеждается в валидности подписи и срока, затем берёт файл по file_id из хранилища (не по пути из браузера).
  • В ответе принудительно ставится безопасный Content-Type и поведение скачивания (например, application/pdf и имя файла для скачивания).

Две защиты, когда ссылка попадает в групповый чат, — это истечение и скоупинг. Истечение лимитирует утечку во времени. Скоупинг значит, что сервер отклонит запрос, если аутентифицированный пользователь/организация не совпадает с тем, что было подписано. Если вы поддерживаете passwordless‑письма, можно скоупить ссылку под сессию или одноразовый токен. Идея одна: ссылка не является универсальным ключом.

Поддержка в итоге получит вопрос: «Моя ссылка истекла». Не решайте это увеличением срока до недели. Безопаснее — после верификации пользователя прислать новую ссылку.

Чеклист и следующие шаги

Если хотите, чтобы подписанные URL действительно защищали приватные файлы, самые безопасные варианты выглядят скучно. Они делают одни и те же проверки каждый раз и никогда не доверяют входам, которые они сами не создали.

Используйте этот чеклист при ревью потока скачивания:

  • Эндпойнт скачивания принимает стабильный ID (например file_id), а не путь или имя файла от пользователя.
  • Вы валидируете подпись и срок и отвергаете неожиданные query‑параметры (никаких «лишних» настроек, которые может подправить атакующий).
  • Вы целенаправленно устанавливаете Content-Type и Content-Disposition (например, принуждаете скачивание, а не позволяете браузеру угадывать).
  • Файлы живут в приватном хранилище, приложение использует принципы наименьших привилегий, а сообщения об ошибках кратки (никаких подсказок «файл существует» или стектрейсов).
  • Вы логируете неудачи (плохая подпись, истёкшая ссылка, отказ в доступе), чтобы видеть паттерны, не сливая деталей пользователю.

Простое ожидание: если кто‑то копирует действующую ссылку с ноутбука и вставляет в другой браузер, она либо остаётся валидной для предназначенного пользователя и временного окна, либо корректно падает. Она не должна стать постоянным публичным эндпойнтом только потому, что её переслали.

Следующие шаги

Если вы укрепляете существующую систему, стартуйте небольшими изменениями и расширяйтесь:

  • Выберите один чувствительный тип файлов (счета, контракты, экспорты) и переместите его за подписанный эндпойнт, который использует ID.
  • Добавьте строгую валидацию: подпись, срок и allowlist параметров. Затем добавьте корректные Content-Type и заголовки скачивания.
  • Сделайте быструю проверку на злоупотребления: попробуйте path traversal строки, добавьте рандомные query‑параметры, измените срок действия и убедитесь, что каждая попытка корректно падает.

Если ваше приложение было сгенерировано ИИ (инструменты вроде Lovable, Bolt, v0, Cursor или Replit), стоит особенно проверить роуты скачивания. FixMyMess (fixmymess.ai) фокусируется на диагностике и ремонте проблем типа сломанных авторизаций, утёкших секретов и небезопасных обработчиков скачиваний, и предлагает бесплатный аудит кода, чтобы оценить риски прежде чем менять систему.

Часто задаваемые вопросы

Why does my “private download” still work when I paste the link into another browser?

“Приватная” загрузка становится публичной, если URL работает сам по себе без повторной проверки прав при каждом запросе. Если кто‑то может скопировать, угадать или автоматизировать такой URL и сервер всё равно вернёт файл, то загрузка фактически публична, даже если кнопка отображалась только залогиненным пользователям.

Aren’t long, unguessable URLs enough to protect downloads?

Случайно сложные имена файлов помогают, но это не защита. Ссылки пересылают, сохраняют в браузере, попадают в логи, вставляются в чаты поддержки или находят автоматические сканеры. Если URL остаётся стабильным и сервер не проверяет прав на стороне сервера, он может работать бесконечно.

What exactly is a signed URL in plain terms?

Подписанный URL — это обычная ссылка для скачивания, но в ней есть подпись, которую ваш сервер может проверить с помощью секретного ключа. Если кто‑то изменит идентификатор файла, срок действия или область действия, подпись перестанет соответствовать, и запрос отклонят до отправки байтов файла.

What should I sign, and what’s the safest way to validate it?

Подписывайте небольшой, жёстко определённый набор полей: идентификатор ресурса, метку истечения и, при необходимости, область (пользователь/организация). Соберите каноническую строку в фиксированном порядке и вычислите HMAC. При проверке на входе отвергайте отсутствующие или некорректные поля, проверяйте время истечения, пересчитывайте HMAC и сравнивайте с использованием сравнения с постоянным временем.

When does a download endpoint become vulnerable to path traversal?

Уязвимость возникает, когда клиент может влиять на путь в файловой системе, даже косвенно. Безопаснее принимать непрозрачный file ID, искать реальный ключ хранилища на сервере, подтверждать права доступа и только затем читать или стримить файл.

Why do content-type headers matter if the URL is signed?

Потому что можно случайно вернуть загруженный файл как веб‑страницу. Принудительно задавайте Content-Disposition: attachment, устанавливайте доверенный Content-Type и добавляйте X-Content-Type-Options: nosniff, чтобы браузер не пытался «угадывать» и не рендерил файл как HTML или скрипт.

How long should an expiring download link last?

Выбирайте самый короткий срок, который позволяет пользователю выполнить задачу. Для просмотра документа часто хватает 5–15 минут, для большого экспорта — 30–60 минут. Если операцию можно возобновить позже, потребуйте нового запроса после повторной аутентификации вместо долгоживущей общей ссылки.

Can someone share a signed URL and let others download the file?

Подписанные URL снижают риск нецелевого распространения, но не препятствуют пересылке действующей ссылки. Для более строгого контроля включайте в подпись userId/orgId или session, а также по‑прежнему выполняйте проверку прав доступа на сервере при запросе.

How do I rotate signing keys without breaking active links?

Включите небольшой идентификатор ключа kid и оставляйте старые ключи доступными лишь кратко, пока действующие ссылки не истекут. Короткий срок жизни ссылок снижает необходимость поддерживать старые ключи долго. Никогда не помещайте подписи в клиентский код или детальные логи.

My app was generated by an AI tool—what’s the quickest way to check if downloads are unsafe?

Многие AI‑сгенерированные приложения поставляют роуты скачивания, которые лишь «прячут» URL: принимают file=..., пропускают строгую валидацию или устанавливают небезопасные заголовки. Если у вас прототип с утечками или запутанной авторизацией, FixMyMess (fixmymess.ai) может провести бесплатный аудит кода и затем исправить поток загрузки: авторизация, валидация подписей и безопасные заголовки.