# Ru

> Полный аудит безопасности ВСЕГО репозитория the-platform (все backend-сервисы, the-frontend, встраиваемые виджеты/расширения, общие библиотеки libs/*, инфраструктурные конфиги helm/k8s/docker) — три независимых среза (автоматизированное сканирование SCA/SAST/secret-scan/IaC, построчный код-ревью по зонам, архитектурный обзор), детальный чек-лист по 14 категориям (auth/authz, мультитенантность, websocket, internal API, инъекции, SSRF, XSS, секреты/PII, файлы, зависимости, docker, k8s/helm, обработка ошибок, CI/CD), находки с file:line и сценарием эксплуатации, и итоговым отчётом для руководства. Используй когда просят провести полный аудит безопасности всей кодовой базы/репозитория/платформы целиком, найти уязвимости по всему проекту, перепроверить статус находок из предыдущего security-аудита, или оценить общую готовность платформы к обработке персональных данных клиентов с точки зрения безопасности — даже если пользователь не произносит слово "аудит" буквально, а говорит "давай проверим весь проект на дыры в

- Skill: `smirnovalex-qa/ru-22` (Agent Skill)
- Install (CLI): `npx skillmds@latest add smirnovalex-qa/ru-22`
- Raw SKILL.md: https://api.skillmd.com/api/skills/smirnovalex-qa/ru-22/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: smirnovalex-qa (https://skillmd.com/u/smirnovalex-qa)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/smirnovalex-qa/ru-22

---

# Полный аудит безопасности репозитория

Для проекта the-platform: микросервисная CRM-платформа, обрабатывающая
персональные данные клиентов. Безопасность — критический приоритет, а не
формальность. Аудит должен находить реальные, эксплуатируемые проблемы с
привязкой к file:line, а не составлять общий чек-лист без проверки. Каждая
находка обязана быть подтверждена вручную, а не только упоминанием в выводе
сканера.

## ВХОДНЫЕ ДАННЫЕ

`$ARGUMENTS` — необязательно путь к отчёту предыдущего аудита для сравнения
"было → стало". Если не передан — ищи сам: реестр прошлых находок лежит в
`docs/bugs/security_audit/` (по каждой находке зафиксирован вердикт:
подтвердилась / false positive / уже исправлена), а регрессионная проверка
по нему — `scripts/verify_audit_fixes.py`, если он есть в репозитории.

Это аудит ВСЕГО репозитория. Если задача на самом деле касается только
одной фичи/ветки/PR/YouTrack-задачи — используй `security-audit-feature`
вместо полного разбора всей кодовой базы (иначе периметр окажется
избыточным, а находки не будут привязаны к тому, что реально нужно
проверить перед конкретным релизом).

## КЛЮЧЕВОЙ ПРИНЦИП: ВЕРИФИКАЦИЯ, А НЕ ДОВЕРИЕ

Главная причина, по которой аудиты безопасности проваливаются, — принятие
на веру того, что "исправление написано" эквивалентно "уязвимость закрыта".
Это НЕ так. Проверяй каждый фикс адверсариально:

1. Если добавлена проверка (флаг, HMAC-подпись, экранирование, авторизация)
   — убедись, что она ВКЛЮЧЕНА по умолчанию и активна во всех окружениях
   (dev/staging/prod), а не только реализована в коде и выключена флагом.
2. Если добавлено экранирование ввода — проверь ПОЛНОТУ: экранированы ли
   все спецсимволы (одиночная кавычка, двойная кавычка, обратный слэш,
   null-байт, юникод-обход), а не только очевидный случай. Одна незакрытая
   дыра в экранировании = уязвимость не закрыта.
3. Если защита (auth-секрет, middleware, RBAC-фильтр) применена к одному
   эндпоинту/сервису — проверь ВЕСЬ класс однотипных эндпоинтов/сервисов.
   Точечный фикс без покрытия всего класса — это не фикс, а иллюзия фикса.
   Ищи "братьев и сестёр" уязвимого паттерна по всей кодовой базе (grep по
   сигнатуре, а не по имени функции).
4. Если в коде есть RBAC/switch/if-else по ролям — всегда проверяй ветку
   "иначе" (default case). Отсутствие else-ветки с явным отказом в доступе
   — это разрешение по умолчанию, то есть дыра.
5. Не принимай объяснение "это устаревшая версия" или "это уже поправлено"
   без самостоятельной проверки текущего состояния репозитория. Если раньше
   был отчёт с найденными рисками — перепроверь каждый пункт по текущему
   коду, независимо от того, что утверждает команда. Начни сверку с
   `docs/bugs/security_audit/`, а не с чистого листа, и прогони
   `scripts/verify_audit_fixes.py` для регрессионной проверки, если он
   есть. Если новая находка фактически совпадает с уже трекнутым и
   осознанно принятым там риском (например, отключённый networkPolicy,
   одна реплика для HA-компонента) — сошлись на существующий файл вместо
   дубликата, и отметь отдельно только если текущее изменение делает риск
   хуже, чем он был зафиксирован.
6. Формулируй разницу между статусами явно: "не исправлено" / "исправлено
   формально (код есть, защиты нет)" / "исправлено выборочно (часть класса
   покрыта)" / "исправлено полностью" / "новая находка".

## МЕТОДОЛОГИЯ: ТРИ НЕЗАВИСИМЫХ СРЕЗА

Проведи аудит тремя независимыми методами и не позволяй одному срезу
подменять другой — у них разная слепая зона.

### СРЕЗ 1 — Автоматизированное сканирование

- **Зависимости (SCA)**: pip-audit/safety для Python-сервисов, npm audit
  для фронтенда и Node-сервисов, grype и/или trivy fs/image для всех
  манифестов зависимостей и Docker-образов. Зафиксируй разбивку
  critical/high/medium/low и версии пакетов.
- **Секреты в репозитории**: gitleaks или trufflehog по ПОЛНОЙ истории git
  (не только по HEAD — секреты, once committed, остаются в истории даже
  после удаления файла), плюс trivy secret-scanner по рабочему дереву.
  Явно укажи, какие директории/пути сканер НЕ покрыл (исключения в
  конфиге сканера, submodule, генерируемые артефакты) — "0 находок" по
  непокрытой директории не является доказательством отсутствия секретов.
- **SAST**: semgrep (правила для Python/JS/TS: injection, ssrf, insecure
  deserialization, hardcoded secrets, weak crypto) и/или bandit для Python.
- **IaC/Kubernetes**: checkov и/или kube-linter по всем helm-чартам и
  манифестам — networkPolicy, securityContext, resources,
  readOnlyRootFilesystem, capabilities, image tags (:latest запрещён),
  privileged containers, hostPath/hostNetwork.
- **Container security**: trivy image по каждому собираемому образу — CVE
  в базовом образе, отсутствие USER (root по умолчанию), лишние пакеты.

### СРЕЗ 2 — Ручной построчный разбор кода

Раздели кодовую базу на независимые зоны и разбери КАЖДУЮ построчно (не по
диагонали, не полагаясь только на grep-паттерны):

- Каждый backend-сервис отдельно (gateway, все `*-service` директории в
  `services/`).
- Frontend/SPA (`the-frontend` и любые другие клиентские приложения).
- Браузерные расширения/встраиваемые виджеты (chat-widget и т.п.) — код
  выполняется на стороне клиента ВНЕ вашего периметра, любая XSS там видна
  конечным пользователям ваших клиентов, это репутационный и регуляторный
  риск, а не только внутренний техдолг.
- Инфраструктурные конфиги (`helm/`, k8s-манифесты, docker-compose,
  CI/CD пайплайны).
- Общие библиотеки (`libs/shared_auth`, `libs/shared_metrics` и аналоги) —
  проверь, подключены ли они как единый пакет или скопированы по сервисам
  (если скопированы — зафиксируй как архитектурный риск: патч безопасности
  не распространяется автоматически).

По каждой зоне ищи (детальный чек-лист ниже) и для каждой находки указывай:
file:line, тип уязвимости, конкретный сценарий эксплуатации (не абстрактно
"может быть уязвимость", а "запрос X с параметром Y даёт результат Z"),
severity, статус (см. выше).

### СРЕЗ 3 — Архитектурный обзор

Независимо от построчного разбора оцени, способна ли текущая архитектура
УДЕРЖИВАТЬ безопасность со временем, а не только не иметь дыр сегодня:

- Размер файлов и смешение слоёв (HTTP + SQL + бизнес-логика + RBAC в одном
  файле — ревьюить и тестировать такое практически невозможно, дефекты
  систематически проходят).
- Количество механизмов межсервисной коммуникации (чем больше разных
  способов вызова — тем меньше шансов на единую точку внедрения политики
  авторизации).
- Дублирование общих библиотек безопасности по сервисам вместо единого
  пакета.
- Наличие/отсутствие процесса: обязательное код-ревью перед мержем,
  блокирующий security-гейт в CI, независимая проверка закрытия предыдущих
  находок (не по самоотчёту команды).
- Небезопасные значения по умолчанию как системный паттерн (если один флаг
  выключен по умолчанию — проверь, не системная ли это практика: другие
  флаги/фичи безопасности в проекте тоже выключены по умолчанию?).

## ДЕТАЛЬНЫЙ ЧЕК-ЛИСТ ПО КАТЕГОРИЯМ

1. **Аутентификация и авторизация**
   - Все ли эндпоинты, требующие аутентификации, её действительно проверяют
     (нет ли "забытых" открытых маршрутов, особенно /public/*, /internal/*,
     /health, /debug)?
   - Саморегистрация: какая роль выдаётся по умолчанию? is_active=True
     сразу или через подтверждение (email/admin approval)? Может ли внешний
     человек через саморегистрацию получить доступ к чужим данным?
   - RBAC/фильтрация по ролям: для КАЖДОЙ ветки ролей — что происходит для
     роли, не попавшей ни в одну явную ветку (default/else)? Приводит ли
     это к утечке данных (например, отсутствие фильтра по
     assigned_user_id/owner_id)?
   - Заголовки-контексты пользователя (X-User-Context и аналоги): подписаны
     ли криптографически? Проверяется ли подпись на приёме, ВКЛЮЧЕНА ли эта
     проверка по умолчанию во всех сервисах, которые доверяют этому
     заголовку?
   - IDOR/BOLA: можно ли, меняя ID в URL/body, получить доступ к чужим
     объектам (контакты, сделки, файлы, диалоги)?
   - Broken function level authorization: доступны ли админские операции
     (массовое удаление, экспорт, wipe-data) без проверки роли?
   - Session/token management: где хранятся токены (localStorage vs
     httpOnly cookie), есть ли инвалидация при логауте/смене пароля, есть
     ли ограничение по времени жизни.
   - Хранение паролей: алгоритм хеширования (bcrypt/argon2 vs md5/sha1),
     наличие соли, work factor. Есть ли MFA/2FA хотя бы для админских
     ролей.
   - CORS: `Access-Control-Allow-Origin` не равен `*` вместе с
     `Allow-Credentials: true`; Origin из запроса не отражается в ответ без
     сверки с allow-list.
   - Rate limiting/брутфорс-защита на login, сброс пароля, OTP/2FA-коды —
     есть ли лимит попыток и блокировка/задержка при превышении.
   - Mass assignment/over-posting: принимает ли API произвольные поля тела
     запроса (role, is_admin, company_id, balance и т.п.) при
     create/update, или список разрешённых полей — explicit whitelist.

2. **Мультитенантность (изоляция между компаниями-клиентами)** — это SaaS
   CRM с несколькими компаниями-клиентами на общей инфраструктуре; утечка
   данных МЕЖДУ компаниями тяжелее по последствиям, чем IDOR внутри одной
   компании (регуляторный риск, доверие сразу всех клиентов платформы),
   поэтому разбирай отдельно от общего IDOR-пункта выше, а не как его
   частный случай.
   - Для КАЖДОЙ точки чтения/записи данных (REST-хендлер, WebSocket-
     подписка, кэш-ключ, поисковый индекс, очередь событий, экспорт/отчёт)
     — фильтруется ли она по company_id/tenant_id на уровне запроса к БД
     (WHERE company_id = ...), а не только проверкой на уровне UI/роутера.
   - Совпадение company_id проверяется явно (сравнение значения из
     токена/контекста с company_id самой записи), а не подразумевается тем,
     что "запрос и так идёт из авторизованной сессии".
   - Массовые операции, экспорт, аналитика/дашборды — не пересчитывают ли
     они агрегаты по всем компаниям вместо своей.
   - Общие ресурсы между сервисами (Redis-ключи, RabbitMQ-очереди,
     файловое хранилище) — не может ли ключ/имя коллизировать между
     разными компаниями при одинаковых внутренних ID (например, contact_id
     уникален внутри компании, но не глобально).

3. **WebSocket / realtime**
   - Проверяется ли токен/роль/company_id при установке соединения
     (connect), И отдельно — при каждой подписке на канал/комнату/диалог
     (join), а не только один раз на connect.
   - Может ли клиент подписаться на чужой канал, подставив/угадав room-id,
     dialog-id, user-id, если сервер не сверяет владельца канала с текущим
     пользователем.
   - Рассылка событий (broadcast) — фильтруется ли получатель по
     company_id/роли перед отправкой, или сервер полагается на то, что
     клиент "просто не подписан" на чужие данные.

4. **Internal-API между сервисами**
   - Пройдись по ВСЕМ `/internal/*` эндпоинтам во ВСЕХ сервисах и построй
     таблицу: сервис | эндпоинт | требует ли shared-secret/mTLS |
     проверяется ли этот секрет фактически (а не только объявлен в
     переменных окружения). Ищи расхождения — один и тот же класс операций
     (send-message, delete-by-id, wipe-data, sync) защищённый в одном
     сервисе и незащищённый в соседнем — это системная дыра.
   - Может ли internal-эндпоинт быть вызван напрямую снаружи кластера (нет
     ли дополнительного network-level ограничения, если auth слабый)?

5. **Инъекции (SQL / NoSQL / Command / Template / Deserialization)**
   - Найди все места сборки запросов конкатенацией/f-string/format вместо
     параметризованных запросов или ORM. Особое внимание — публичным
     query-параметрам (фильтры дашбордов, поиск, сортировка).
   - Если есть экранирование "вручную" — проверь полноту (обратный слэш,
     юникод, вложенные кавычки).
   - Command injection: любые subprocess/os.system/exec с интерполяцией
     пользовательского ввода.
   - Server-side template injection: если пользовательский ввод попадает в
     шаблонизатор.
   - NoSQL injection: если используется Mongo/аналоги — операторы ($where,
     $ne) из пользовательского ввода.
   - Небезопасная десериализация: `pickle`, `yaml.load` без `SafeLoader`,
     `jsonpickle`, `eval`/`exec` над данными, пришедшими из очереди,
     вебхука или межсервисного вызова, а не только из HTTP-запроса
     напрямую.

6. **SSRF (Server-Side Request Forgery)**
   - Любой код, который делает исходящий HTTP-запрос по URL, пришедшему от
     пользователя или из внешней системы (вебхуки, media_url, callback_url,
     интеграции с CRM/мессенджерами) — есть ли allow-list доменов,
     блокировка приватных/internal IP-диапазонов (169.254.x.x, 10.x,
     172.16-31.x, 192.168.x, 127.x, metadata-эндпоинты облаков)?
   - Проверяется ли подпись/источник вебхука перед тем, как система
     инициирует ответный запрос по URL из тела вебхука?

7. **XSS (включая Stored XSS в клиентских виджетах)**
   - Любое использование innerHTML/dangerouslySetInnerHTML/document.write с
     недоверенными данными.
   - Встраиваемые на сторонних сайтах виджеты — это код, исполняющийся в
     браузере конечных посетителей сайтов ваших клиентов. Уязвимость там
     имеет более широкий радиус поражения, чем внутренняя XSS —
     квалифицируй с учётом этого при оценке severity.
   - CSP (Content-Security-Policy) настроен ли и достаточно ли строг.
   - Clickjacking: заголовки `X-Frame-Options`/`frame-ancestors` —
     предотвращают ли встраивание основного приложения (не виджета) в
     чужой iframe.

8. **Работа с секретами и PII**
   - Секреты в коде/конфигах, отслеживаемых git (values-*.yaml,
     *-secrets.yaml, .env закоммиченные, hardcoded API keys/tokens в
     исходниках).
   - Скрипты выгрузки персональных данных (дампы контактов/клиентов),
     лежащие в репозитории — сами по себе являются риском независимо от
     прав доступа к репо.
   - Хранение токенов интеграций (Telegram/WhatsApp боты и т.п.) в БД — в
     открытом виде или зашифрованы?
   - Локальные сессии клиентов мессенджеров (например, TDLib-сессии) на
     диске — зашифрованы ли at rest?
   - Проверь git history командой вроде `git log --all --full-history --
     <path>` для файлов, которые сейчас удалены, но могли содержать секреты
     в прошлом.
   - Маскирование секретов в логах (redaction) — работает ли для всех
     типов секретов (bot_token, api_key, access_token, пароли, PII), а не
     только для части.
   - `.env.example`/примеры конфигов — не содержат ли они по ошибке
     реальное значение вместо плейсхолдера; не печатаются ли переменные
     окружения целиком в CI-логи (`env`, `printenv`, debug-вывод конфига
     при старте сервиса).

9. **Загрузка и хранение файлов**
   - Проверка MIME-типа и расширения при загрузке (не доверять
     Content-Type от клиента без валидации содержимого).
   - Ограничение размера файла, защита от zip-бомб/decompression bomb для
     архивов.
   - Публичные эндпоинты раздачи файлов (/public/documents и т.п.) —
     требуют ли аутентификации, если файлы содержат PII или приватные
     данные?
   - Path traversal при формировании пути сохранения/чтения файла из
     пользовательского ввода.
   - Object storage (S3/MinIO): публичность бакетов, версионирование,
     репликация.

10. **Зависимости и суплай-чейн**
    - Полная разбивка уязвимостей по критичности и по сервисам (не общая
      цифра, а по каждому сервису отдельно — где сосредоточен риск).
    - Совпадающие критичные библиотеки, используемые в нескольких сервисах
      разных версий (например, разные версии одного фреймворка в разных
      сервисах — означает, что патч придётся катить N раз).
    - Docker base images: используются ли устаревшие/EOL версии, теги
      :latest вместо пиннинга по digest/версии.
    - Lock-файлы (poetry.lock, package-lock.json, uv.lock) — закоммичены
      ли, соответствуют ли заявленным версиям.
    - Dependency confusion: внутренние пакеты (libs/shared_auth,
      libs/shared_metrics и аналоги) — устанавливаются ли из приватного
      индекса/по локальному пути или по голому имени с публичного
      PyPI/npm, где одноимённый публичный пакет мог бы их подменить.

11. **Docker / контейнеры**
    - USER указан (non-root) в каждом Dockerfile — построй таблицу по всем
      образам.
    - readOnlyRootFilesystem, drop: ALL capabilities,
      allowPrivilegeEscalation: false в securityContext.
    - Секреты не передаются через ARG/ENV в Dockerfile (попадают в историю
      слоёв).
    - Multi-stage build для исключения build-инструментов и
      dev-зависимостей из финального образа.

12. **Kubernetes / Helm**
    - networkPolicy для баз данных, кэшей, очередей (Redis, PostgreSQL,
      RabbitMQ) — включены ли в prod, ограничивают ли трафик только
      доверенными подами.
    - resources requests/limits заданы (не пустой {} по умолчанию) для
      предотвращения noisy neighbor и DoS через исчерпание ресурсов.
    - liveness/readiness пробы для сервисов ядра бизнес-логики.
    - Секреты через Kubernetes Secrets/внешний secret-manager, а не в
      values.yaml открытым текстом.
    - Single point of failure: количество реплик для stateful-компонентов
      (Redis, RabbitMQ, MinIO, БД) в prod — 1 реплика для критичного
      компонента является риском доступности, фиксируй отдельно от
      security-находок, но не игнорируй.
    - Стратегия бэкапов БД — задокументирована и автоматизирована ли.

13. **Обработка ошибок и наблюдаемость**
    - Паттерн "молчаливого проглатывания" ошибок (broad except с
      логированием и возвратом None/пустого результата без re-raise/
      алерта) — маскирует ли это сбои безопасности (например, неудавшуюся
      проверку авторизации, которая по ошибке трактуется как "разрешено")?
    - Логируются ли security-события (неудачные попытки авторизации,
      изменение ролей, массовые удаления) отдельно и доступны ли для
      мониторинга/алертинга.
    - Утечка внутренней информации через сообщения об ошибках (стектрейсы,
      версии библиотек, структура БД) в ответах API наружу.

14. **CI/CD и процесс**
    - Есть ли обязательное код-ревью перед мержем в защищённые ветки.
    - Есть ли блокирующий security-гейт в CI (SCA/SAST/secret-scan),
      который реально останавливает мерж при critical/high находках, а не
      просто печатает предупреждение.
    - Есть ли регрессионный чек-лист по ранее найденным уязвимостям,
      который прогоняется перед каждым релизом.
    - Кто владеет решением "мержить/не мержить" при найденной уязвимости —
      есть ли явный security owner с правом блокировки.
    - CI script injection: интерполируется ли непроверенный внешний ввод
      (заголовок PR, имя ветки, issue title) напрямую в шаг `run:`
      пайплайна — классический вектор кражи CI-секретов, который SCA/SAST
      не ловят.
    - Публичные админ/debug-эндпоинты в проде: Swagger/OpenAPI UI,
      admin-панели фреймворка, интерактивные debug-консоли (например,
      Werkzeug) — доступны ли без аутентификации на боевом окружении.

## EDGE CASES, КОТОРЫЕ ЧАСТО ПРОПУСКАЮТ

- Функциональность, защищённая на UI-уровне (кнопка скрыта), но доступная
  напрямую через API без проверки на бэкенде.
- Race condition в проверках "check-then-act" (например, проверка роли и
  последующее действие не атомарны, между ними можно вклиниться).
- Отличия в поведении для "мягко удалённых" (soft-deleted) записей —
  доступны ли они через API, который не учитывает флаг удаления.
- Массовые операции (bulk endpoints) — часто имеют более слабую
  авторизацию, чем их единичные аналоги, потому что добавлены позже
  "по-быстрому".
- Вебхуки от внешних систем — проверяется ли подпись/источник, или
  доверяем любому телу запроса, пришедшему на публичный URL.
- Feature-флаги безопасности, выключенные "временно для отладки" и
  забытые в этом состоянии в конфиге по умолчанию.
- Различия между окружениями (dev/staging/prod) — фикс, применённый в
  одной конфигурации helm-values, может отсутствовать в другой.
- Экспорт данных (CSV/Excel/PDF генерация) — проверяется ли авторизация
  на экспортируемый объём данных так же строго, как на обычное чтение
  через UI.
- Повторное использование одного и того же секрета/ключа в нескольких
  сервисах — компрометация одного сервиса даёт доступ к остальным.
- Устаревшие/неиспользуемые эндпоинты, оставленные в коде "на всякий
  случай" без документации и без auth, потому что "никто ими не
  пользуется".

## ШКАЛА SEVERITY

Фиксированная шкала нужна, чтобы находки были сравнимы между собой и между
повторными аудитами (иначе таблица сопоставления "предыдущий отчёт →
текущий" теряет смысл, если severity расставляется каждый раз по-новому).
Та же шкала используется в скилле `security-audit-feature`.

- **Critical**: неаутентифицированный внешний атакующий получает полный
  компромисс (RCE, доступ ко всем данным всех компаний-клиентов, обход
  аутентификации целиком).
- **High**: аутентифицированный пользователь (в т.ч. с минимальной ролью)
  получает доступ к чужим данным/привилегиям — включая межтенантный доступ
  (см. раздел 2), либо неаутентифицированный атакующий получает доступ к
  данным одной компании/одного пользователя.
- **Medium**: требует специфичных условий (гонка, конкретная роль, MITM,
  социальная инженерия) или ограничивается ограниченной утечкой
  метаданных/DoS отдельного компонента без потери данных.
- **Low**: нарушение best practice без прямого сценария эксплуатации на
  момент аудита (например, отсутствующий заголовок безопасности без
  известного вектора атаки в текущей архитектуре).

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

## ФОРМАТ ОТЧЁТА

1. Executive summary (для руководства, без технического жаргона): что
   критично, что рискует бизнесом/репутацией/регуляторикой, что делать в
   первую очередь.
2. Таблица KPI: число critical/high/medium/low находок, число уязвимостей
   зависимостей по критичности, % контейнеров под non-root, число
   незакрытых рисков из предыдущего отчёта (если это повторный аудит).
3. Если это повторный аудит — таблица сопоставления "пункт предыдущего
   отчёта → текущее состояние (file:line) → статус (не исправлено /
   формально / выборочно / исправлено)". Не принимай прошлые объяснения
   без перепроверки.
4. Раздел "исправлено, но не работает" отдельно — это самый показательный
   сигнал о зрелости процесса, выделяй его явно.
5. Полный список находок с привязкой file:line, конкретным сценарием
   эксплуатации, severity (CVSS-подобная оценка или
   critical/high/medium/low) и рекомендацией.
6. Раздел "что сделано хорошо" — сильные паттерны в кодовой базе, которые
   стоит тиражировать, а не переделывать. Аудит без баланса теряет доверие
   и её сложнее использовать для мотивации команды.
7. План действий по срокам: 24-48 часов (эксплуатируемые сегодня векторы),
   1 неделя (остальные critical), 2-4 недели (процесс и архитектура),
   решения уровня руководства (владелец безопасности, независимая
   переверификация, архитектурные решения, которые нельзя решить
   точечными патчами).
8. Раздел "методология и ограничения покрытия" — какие инструменты
   использовались, какие директории/сервисы НЕ были просканированы и
   почему, чтобы отсутствие находок в непокрытой зоне не читалось как
   "там всё чисто".

## ПРАВИЛА ОФОРМЛЕНИЯ НАХОДОК

Для каждой находки обязательны:

- Стабильный ID находки (например, `SEC-2026-08-04-001`) — чтобы при
  повторном аудите можно было сослаться на конкретную находку по ID, а не
  пересказывать её заново своими словами (пересказ может незаметно
  "уехать" от исходной формулировки и сломать сопоставление статусов между
  аудитами).
- Путь к файлу и номер строки (или диапазон).
- Название уязвимости и категория (можно сослаться на OWASP Top 10 / OWASP
  API Security Top 10 / CWE).
- Конкретный сценарий эксплуатации: "если сделать запрос X с параметром Y,
  система вернёт/сделает Z" — не абстрактные формулировки вроде "может быть
  уязвимость".
- Severity с обоснованием (кто может использовать: аутентифицированный
  пользователь / любой внешний / только внутренняя сеть; что теряется:
  чтение данных / запись / полный компромисс).
- Статус относительно предыдущего аудита, если применимо.
- Рекомендация по исправлению — конкретная (не "улучшить безопасность", а
  "добавить else-ветку с явным отказом", "включить флаг X по умолчанию",
  "заменить f-string на параметризованный запрос").

## ЗАПУСК АУДИТА (практическая инструкция)

1. Определи периметр: перечисли все сервисы (директории верхнего уровня в
   `services/`), фронтенд-приложения, встраиваемые виджеты/расширения,
   инфраструктурные конфиги.
2. Прочитай реестр прошлых находок в `docs/bugs/security_audit/` ПЕРЕД
   началом ручного разбора, если он есть, — это готовый источник уже
   известных проблем, не дублируй работу, а проверь, устранены ли они.
3. Запусти автоматизированные инструменты СРЕЗА 1 по каждому
   сервису/образу/чарту, где это возможно в текущем окружении, сохрани
   сырой вывод для приложений к отчёту. Отфильтруй заведомые false
   positive (тестовые фикстуры, placeholder-значения вида
   "changeme"/"example_key") явным списком в разделе ограничений, а не
   молча — чтобы было видно, что они рассмотрены, а не пропущены.
4. Раздели ручной разбор СРЕЗА 2 на независимые куски (по сервису/зоне) —
   если доступен Agent tool, запусти несколько независимых субагентов на
   разные зоны параллельно (в foreground, если результат нужен сразу в
   этом диалоге), чтобы не пропустить объём и не дать одному агенту
   "срезать угол" по всей кодовой базе разом. Кодовая база крупная
   (десяток+ сервисов) — каждому субагенту передай конкретный список
   файлов/директорий его зоны и применимые разделы этого скилла (чек-лист,
   шкалу severity, формат находки), а не пересказ своими словами. Записывай
   подтверждённые находки в промежуточный файл сразу по мере разбора
   каждой зоны, а не держи их только в контексте до финального отчёта: при
   сжатии длинного диалога ранее найденное иначе может потеряться.
5. Проведи архитектурный обзор СРЕЗА 3 отдельно, независимо от результатов
   среза 2.
6. Сведи все три среза в единый отчёт по формату выше, убери дубликаты, но
   не объединяй находки разной природы (secret-scanner нашёл файл ≠ ручной
   разбор подтвердил, что секрет реальный и активный — фиксируй оба факта,
   если они есть).
7. Если это повторный аудит — обязательно перепроверь КАЖДЫЙ пункт
   предыдущего отчёта по текущему состоянию кода, а не полагайся на
   статус, заявленный командой.
8. Явно укажи, какие проверки НЕ были выполнены (ограничения окружения,
   нет доступа к прод-секретам, нет доступа к рантайм-логам и т.п.) — это
   часть честного отчёта, а не его слабость.
9. Сохрани финальный отчёт файлом в `docs/bugs/security_audit/` (например,
   `full-audit-<дата>.md`) — это то же место, где хранится реестр прошлых
   находок, и следующий повторный аудит должен его найти при сверке.

Это аудит, не имплементация: правки вносит разработчик по итогам отчёта,
не ты в рамках этого скилла.

