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

Один неудачный лог может превратить отладку в утечку: в файл попадают токен сессии, полный URL с email пользователя, тело запроса и трассировка с SQL-параметрами. Через сутки эти данные уже могут находиться не только на сервере, но и в Elasticsearch, системе алертов, резервной копии и тикете поддержки. Ниже — практический разбор для веб-приложений и API: какие значения не писать вовсе, какие заменять, а какие можно оставить при ограниченном сроке хранения.
Главное правило: логируйте событие, а не копию запроса
Логу обычно нужно ответить на четыре вопроса: что произошло, когда, где и с каким результатом. Полный HTTP-запрос для этого почти никогда не требуется. Он добавляет заголовки, cookies, параметры URL и тело, где могут находиться секреты и персональные данные.
Если значение не помогает однозначно объяснить инцидент, его не должно быть в логе.
Безопасная запись обычно содержит время, тип события, результат, идентификатор операции, имя сервиса и технический correlation ID1. Идентификатор пользователя лучше передавать в отдельном поле только тогда, когда он нужен для расследования и защищён от свободного доступа.
Сноска. Correlation ID — уникальный идентификатор цепочки связанных операций. Он помогает найти все записи одного запроса или заказа, но сам по себе не должен содержать email, телефон или другой узнаваемый признак пользователя.
Что нельзя писать в логи
Секреты и данные для входа
Эти значения не должны попадать в логи ни в успешном, ни в ошибочном сценарии:
- пароли, PIN-коды, одноразовые коды подтверждения и ответы на секретные вопросы;
- токены доступа, refresh-токены, API-ключи, cookies сессии и заголовок Authorization;
- закрытые ключи, сертификаты вместе с приватным ключом, строки подключения с паролями;
- полные ссылки для сброса пароля или подтверждения email, если в них есть секретный параметр;
- резервные коды, webhook-секреты и подписи запросов.
Маскировать секрет нужно до записи, а не после отправки в хранилище. Если токен уже оказался в логе, удаление строки не отменяет его попадание в резервные копии и реплики: секрет следует отозвать или заменить по правилам конкретного сервиса.
Платёжные и идентификационные данные
Не записывайте полный номер банковской карты, код безопасности, данные документа, полный номер банковского счёта и снимки документов. Для диагностики платёжного сбоя обычно достаточно идентификатора операции, кода ответа платёжного провайдера и последних четырёх цифр карты — только если такой формат разрешён вашей моделью угроз и правилами провайдера.
С фотографиями, медицинскими сведениями, данными о местоположении и другой чувствительной информацией нужен ещё более строгий режим. В идеале приложение вообще не должно видеть и логировать эти поля: их надо исключать на границе приёма запроса.
Персональные данные, замаскированные только на вид
Email, телефон, IP-адрес, имя, адрес доставки, номер заказа и внутренний user ID могут связывать запись с конкретным человеком. Внутренний идентификатор не становится безопасным только потому, что выглядит как случайная строка: если команда может сопоставить его с пользователем, это всё ещё персонализированный признак.
Односторонное хеширование тоже не универсальное решение. Для короткого телефона или email возможен перебор вариантов. Если значение не нужно восстанавливать, используйте контролируемый способ псевдонимизации с ограниченным доступом к таблице соответствий; если нужно — храните исходное значение в защищённой бизнес-системе, а не в логах.
Что оставить, а что заменить
Полезно разделить поля на три группы ещё до того, как команда выберет формат JSON-логов.
| Тип данных | Пример | Решение | Почему |
|---|---|---|---|
| Секрет | Authorization, session cookie, API-ключ | Не записывать; уже утёкшее значение отозвать | Лог может дать прямой доступ к аккаунту или сервису |
| Содержимое запроса | Пароль, код подтверждения, текст формы | Не писать тело целиком; оставить тип операции и результат | В одном поле могут смешаться секреты и чувствительные сведения |
| Идентификатор человека | Email, телефон, имя | Исключить или заменить контролируемым псевдонимом | Не нужен для большинства технических ошибок |
| Технический контекст | Имя сервиса, endpoint, статус, длительность | Оставить | Помогает найти причину без раскрытия содержимого |
| Идентификатор операции | Order ID, request ID, trace ID | Оставить, если он не содержит персональных данных | Позволяет связать события и не копировать весь запрос |
| Сетевой адрес | IP клиента | Оставлять только при обоснованной необходимости и с ограничением доступа | Он может быть связан с конкретным пользователем и раскрывать лишний контекст |
Как проектировать безопасное логирование
- Составьте список событий, а не список объектов. Для входа достаточно записать результат, причину отказа, идентификатор операции и технический контекст. Проверка: в описании события нет фразы «записать весь запрос».
- Задайте разрешённую схему полей. Безопаснее разрешать конкретные поля, чем писать всё и пытаться удалить опасное регулярным выражением. Проверка: у каждого поля есть владелец, назначение и срок хранения.
- Сделайте фильтрацию на источнике. Маскирование должно происходить в приложении или библиотеке логирования до отправки в stdout, файл или агент доставки. Проверка: секрет отсутствует в локальном выводе процесса, а не только в панели поиска.
- Разделите уровни логирования. Debug не должен включаться в продакшене постоянно. Временное расширение логов оформляйте с ограниченным сроком и контролем доступа. Проверка: после завершения диагностики уровень возвращён, а созданные записи имеют понятный срок удаления.
- Ограничьте доступ и срок хранения. Разработчику не всегда нужен доступ к продакшенским персональным данным, а дежурному инженеру не нужна вся история за год. Проверка: есть перечень ролей, сроков хранения, реплик и резервных копий.
Почему маскирование часто ломается
Секрет прячут только в одном месте
Команда фильтрует заголовок Authorization, но забывает cookies, query-параметры, тело POST-запроса или исключение, которое печатает объект целиком. Нужны тесты на все каналы: обычный лог, ошибку валидации, исключение, трассировку и диагностический режим.
Обрезают значение, но оставляют его узнаваемым
Первые символы email, телефона или токена иногда позволяют восстановить личность или использовать значение для поиска в другой системе. Для correlation ID применяйте отдельный случайный идентификатор, а не начало исходной строки.
Удаляют поле после доставки
Фильтр в SIEM не защищает от утечки из локального файла, очереди сообщений, агента сбора или резервной копии. Контроль должен находиться как можно ближе к месту формирования записи.
Считают ошибку безопасной по умолчанию
Текст исключения может содержать SQL, путь к файлу, параметры подключения или тело запроса. Внешнему клиенту возвращайте короткий код ошибки и request ID, а в защищённый лог — только нужный технический контекст, предварительно удалив секреты.
Как проверить систему перед запуском
Проверку стоит проводить не по нескольким успешным запросам, а по сценариям, где данные чаще всего раскрываются:
- неудачный вход с неверным паролем и одноразовым кодом;
- ошибка валидации формы с email, телефоном и платёжными полями;
- исключение при обращении к базе и внешнему API;
- запрос с cookies, Authorization и чувствительными query-параметрами;
- запуск временного debug-режима и его отключение;
- копирование записи в систему мониторинга и экспорт в резервную копию.
Ищите не только названия полей, но и характерные шаблоны: длинные токены, строки, похожие на JWT, адреса электронной почты, номера телефонов и значения из тестовых секретов. Тестовые секреты должны быть уникальными, чтобы было видно, на каком этапе они появились.
Где подход ломается
Полностью обезличенный лог не всегда позволяет расследовать злоупотребление: без устойчивого идентификатора нельзя связать серию событий. Обратная крайность — сохранять всё «на всякий случай» — повышает ущерб от компрометации и усложняет контроль доступа. Компромисс выбирают для каждого события отдельно: оставить технический ID, ограничить срок хранения, разделить доступ и хранить связь с пользователем в другой системе.
Отдельная тема — юридические основания обработки и сроки хранения персональных данных. Они зависят от страны, роли компании и конкретного процесса; техническая маскировка не отменяет организационные требования.
Что делать дальше
Начните с инвентаризации: перечислите все места, где появляются логи, кто их читает и куда они копируются. Затем добавьте автоматический тест, который отправляет в приложение тестовые секреты и проверяет stdout, файлы, трассировки и систему сбора. На продакшене следите не только за объёмом логов, но и за долей записей с запрещёнными полями, сроком хранения и количеством сотрудников с доступом к сырым данным.
Версия и применимость. Материал не привязан к конкретной библиотеке логирования или версии фреймворка: правила относятся к веб-приложениям, API и сервисам, которые отправляют структурированные или текстовые логи. Синтаксис фильтров нужно сверять с документацией используемого стека.
Персональный стилист: Фасоны по фото, капсульный гардероб, сочетания цветов.
Спросить за 12 ₽Источники: OWASP Logging Cheat Sheet, NIST SP 800-92, Guide to Computer Security Log Management
Частые вопросы
Можно ли логировать email пользователя для поиска ошибки?
Можно ли оставлять последние четыре цифры номера карты?
Что делать, если пароль или токен уже попал в лог?
Достаточно ли замаскировать персональные данные в SIEM?
Можно ли включить debug-логирование в продакшене на время?
Хеш email делает его безопасным для логов?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.