Зачем вообще думать о секьюрности кэша
Браузерный кэш обычно воспринимают как штуку “про скорость”: меньше запросов, быстрее страница. Но для разработчика это ещё и тихий источник утечек. Если конфиденциальные ответы попадают в кэш, они могут остаться в истории браузера, в профиле на общем компьютере, в прокси или CDN. За последние три года в отчётах Verizon DBIR и OWASP доля инцидентов из‑за неправильных настроек (включая кэширование) колебалась в районе 12–18% от всех проблем с конфигурацией. То есть это не экзотика, а вполне реальный класс уязвимостей, который часто недооценивают.
Кратко о том, как работает браузерный кэш
Браузер запоминает ответы по URL и набору заголовков: Cache-Control, Expires, ETag и прочим. Дальше при повторном заходе он решает, можно ли взять данные из локального хранилища или идти к серверу. Проблема в том, что с точки зрения браузера html для банковской страницы и статический CSS выглядят одинаково — это просто ответы HTTP. Если вы сами не подскажете, что кэшировать нельзя, он попробует оптимизировать. По данным HTTP Archive за 2022–2024 годы, заголовок Cache-Control присутствует примерно у 85–90% ответов, но защищающие флаги вроде no-store и private используются значительно реже.
Где именно кэш может “подставить”

Когда речь про настройку кэширования в браузере для безопасности сайта, важно помнить, что кэш существует не только в браузере пользователя. Данные могут сохраняться:
— в локальном кэше браузера и истории
— в proxy / корпоративных шлюзах
— на уровне CDN, если включено кэширование HTML
— в сервис‑воркерах и IndexedDB, если их так запрограммировали
При этом любое общее рабочее место, коворкинг, семейный компьютер превращается в точку риска. Оставили вкладку интернет‑банка, нажали назад — и следующий пользователь может увидеть страницу из кэша, если заголовки не запрещают её хранить.
Какие данные нельзя кэшировать никогда

Чтобы понимать, как защитить браузерный кэш конфиденциальных данных https, для начала разберёмся, что относится к “конфиденциалке”. Это не только пароли и номера карт. Под запретом кэширования должны быть: страницы с персональными данными, результаты авторизации, личный кабинет, выписки, заказы с адресами и телефоном, одноразовые токены и ссылки на сброс пароля. По данным исследований OWASP за последние годы, утечки через историю браузера и общий доступ к устройству регулярно встречаются в bug bounty‑отчётах крупных компаний, хотя сами уязвимости часто кажутся “мелочью”.
Базовый набор заголовков для чувствительных страниц
Если говорить про secure headers настройка cache control no store для разработчиков, то “джентльменский набор” выглядит так:
— Cache-Control: no-store, no-cache, must-revalidate
— Pragma: no-cache (для очень старых клиентов)
— Expires: 0 или дата в прошлом
Такая связка говорит: не сохранять, не использовать повторно, всегда уточнять у сервера. Для авторизованных зон обычно добавляют ещё private, чтобы запретить кэширование на прокси и CDN. Главное — не полагаться на HTTPS как на волшебную таблетку: шифрование по пути не отменяет риск хранения данных на диске пользователя.
Шаг 1. Разделите контент на “можно” и “нельзя” кэшировать
Практический подход: сначала составьте карту страниц и API‑эндпоинтов. Отметьте, что можно смело кэшировать (статические скрипты, стили, картинки, шрифты) и что должно всегда приходить “свежим” и без следов в истории. За 2022–2024 годы крупные SaaS‑компании в публичных постмортемах не раз признавали, что проблемы начинались именно с отсутствия такой классификации: все эндпоинты жёстко не кэшировались “на всякий случай” или, наоборот, автоматически попадали под агрессивное кэширование в CDN, включая HTML с персональными данными.
Типичные ошибки на этом шаге
Частая ошибка новичков — навешивать один и тот же Cache-Control для всего сайта через глобальный middleware. В результате или вы теряете в производительности, или случайно кэшируете то, что нельзя. Ещё один распространённый промах — считать, что GET “по определению” безопасен, и позволять CDN кэшировать все GET‑ответы. За последние три года в публичных отчётах о багах не раз всплывали случаи, когда личные данные разных пользователей “переезжали” друг к другу именно из‑за агрессивного кэширования HTML‑страниц по методу GET без учёта cookie и заголовков авторизации.
Шаг 2. Настройте безопасные заголовки ответа
На уровне бэкенда или реверс‑прокси зашиваете правила: для публичного статического контента — длинный max-age и immutable; для защищённых зон — no-store и private. Лучшие практики безопасного кэширования в браузере для веб разработчиков сводятся к принципу: “по умолчанию — нет кэширования для всего, что зависит от пользователя”. Только когда вы уверены, что в ответе нет чувствительных данных, включайте долгосрочное хранение. По данным HTTP Archive, за последние годы доля ответов с агрессивным публичным кэшированием HTML потихоньку снижается — разработчики начинают аккуратнее обращаться с заголовками.
Что именно прописать в коде
Простейший вариант для защищённых страниц: выставить в контроллере или middleware что‑то вроде res.set(‘Cache-Control’, ‘no-store, no-cache, must-revalidate, private’). Для SPA‑приложений важно не забыть и про API-эндпоинты, которые возвращают профиль, платежные данные, уведомления. Часто именно они случайно остаются без нужных заголовков. На уровне nginx или другого прокси не полагайтесь только на глобальные директивы: проверьте, что location для /api и /account перегружает настройки и убирает кэширование. Ошибка в одном location — и вы получите сохранённый JSON с персональными данными в прокси.
Шаг 3. Учитываем CDN и корпоративные прокси
Даже если в браузере всё аккуратно, по пути может стоять CDN или корпоративный прокси, который любит кэшировать GET‑ответы для экономии трафика. Если вы отдаёте приватные данные по HTTPS, кэширование на промежуточных узлах обычно ограничено, но не стоит полностью на это полагаться. За 2022–2024 годы крупные инциденты из‑за публичных CDN, кэширующих приватные HTML‑страницы, случались нечасто, но баг‑репорты на эту тему регулярно появляются в программах вознаграждений. Виноваты, как правило, либо слишком общие правила, либо отсутствие заголовков Vary и private.
Флажки, на которые нужно обратить внимание
При работе с CDN убедитесь, что:
— HTML по умолчанию не кэшируется или кэшируется только для анонимных пользователей
— ответы, зависящие от cookie, помечены Vary: Cookie или вообще исключены из кэша
— есть отдельные правила для /static и для /api, а не один шаблон на весь домен
Новичкам лучше начать с консервативного варианта и постепенно ослаблять ограничения на основе профилирования. Попытка сразу “выжать максимум из CDN” нередко заканчивается кросс‑пользовательскими утечками.
Шаг 4. SPA, сервис‑воркеры и офлайн‑режим
Современные фронты усложняют картину: у вас есть сервис‑воркеры, которые могут кэшировать запросы сами по себе, плюс локальные хранилища — IndexedDB, localStorage. За последние три года в публичных обзорах уязвимостей мобильных и веб‑приложений всё чаще фигурируют проблемы, когда разработчики сохраняли в localStorage токены доступа или целые профили пользователей “для удобства”. Утечка устройства или XSS в таком приложении моментально превращает эти данные в подарок злоумышленнику. Поэтому кэширование через сервис‑воркер нужно проектировать не менее осторожно, чем HTTP‑заголовки.
Правила для офлайн‑функциональности
Если вы делаете офлайн‑режим, чётко разделите: офлайн‑ресурсы (JS, CSS, иконки) и пользовательские данные. Во многих случаях имеет смысл вообще не кэшировать персональные данные в IndexedDB без шифрования. Если всё‑таки нужно — используйте шифрование на стороне клиента и минимизируйте срок хранения. Новичкам стоит сначала запустить версию без офлайн‑кэша для приватных данных и добавить его позже, когда вы чётко понимаете модель угроз. Локальный кэш — это расширение поверхности атаки, а не “просто удобство”.
Статистика и тренды за 2022–2024 годы
Если посмотреть на общие цифры, видно, что тема конфигураций и кэширования остаётся болезненной. В отчётах Verizon DBIR 2022–2024 годов ошибки настройки (misconfiguration) стабильно занимали около 10–20% среди корневых причин инцидентов, а веб‑приложения оставались одним из главных векторов атак. Отдельно HTTP Archive фиксирует высокую долю ответов с Cache-Control, но заметный перекос: для HTML нередко используется либо агрессивное кэширование без учёта приватности, либо наоборот полное отключение кэша, что убивает производительность и толкает команды на рискованные оптимизации.
Проверка и аудит настроек кэширования
Даже опытные разработчики не всегда способны “на глаз” определить, что конкретный ответ небезопасно кэшировать. Поэтому имеет смысл периодически заказывать услуги аудита безопасности веб приложения и кэширования: эксперты пройдут по эндпоинтам, посмотрят HTTP‑заголовки, поведение в разных браузерах и под нагрузкой, проверят логи CDN. Для самостоятельной проверки начните с DevTools в браузере, инструментов вроде Lighthouse, затем подключите сканеры заголовков и простые скрипты, которые обходят основные URL и записывают все Cache-Control. Это не заменит полноценный аудит, но быстро подсветит грубые просчёты.
Чек‑лист и советы для новичков
Чтобы не утонуть в деталях, удобно держать под рукой короткий чек‑лист: всё, что связано с авторизацией и профилем — no-store, private; статику — кэшируем агрессивно и долго; HTML без персональных данных — аккуратно кэшируем, учитывая cookie и язык. Помните, что секьюрность кэширования — это не отдельная галочка, а часть общей архитектуры безопасности. При проектировании флоу сразу задавайте себе вопрос: “Можно ли безопасно вернуть этот ответ из кэша на другом устройстве?”. Если ответ неочевиден, лучше сначала запретите кэш, а затем оптимизируйте осознанно.

