Полный аудит безопасности репозитория
Для проекта the-platform: микросервисная CRM-платформа, обрабатывающая персональные данные клиентов. Безопасность — критический приоритет, а не формальность. Аудит должен находить реальные, эксплуатируемые проблемы с привязкой к file:line, а не составлять общий чек-лист без проверки. Каждая находка обязана быть подтверждена вручную, а не только упоминанием в выводе сканера.
ВХОДНЫЕ ДАННЫЕ
$ARGUMENTS — необязательно путь к отчёту предыдущего аудита для сравнения
"было → стало". Если не передан — ищи сам: реестр прошлых находок лежит в
docs/bugs/security_audit/ (по каждой находке зафиксирован вердикт:
подтвердилась / false positive / уже исправлена), а регрессионная проверка
по нему — scripts/verify_audit_fixes.py, если он есть в репозитории.
Это аудит ВСЕГО репозитория. Если задача на самом деле касается только
одной фичи/ветки/PR/YouTrack-задачи — используй security-audit-feature
вместо полного разбора всей кодовой базы (иначе периметр окажется
избыточным, а находки не будут привязаны к тому, что реально нужно
проверить перед конкретным релизом).
КЛЮЧЕВОЙ ПРИНЦИП: ВЕРИФИКАЦИЯ, А НЕ ДОВЕРИЕ
Главная причина, по которой аудиты безопасности проваливаются, — принятие на веру того, что "исправление написано" эквивалентно "уязвимость закрыта". Это НЕ так. Проверяй каждый фикс адверсариально:
- Если добавлена проверка (флаг, HMAC-подпись, экранирование, авторизация) — убедись, что она ВКЛЮЧЕНА по умолчанию и активна во всех окружениях (dev/staging/prod), а не только реализована в коде и выключена флагом.
- Если добавлено экранирование ввода — проверь ПОЛНОТУ: экранированы ли все спецсимволы (одиночная кавычка, двойная кавычка, обратный слэш, null-байт, юникод-обход), а не только очевидный случай. Одна незакрытая дыра в экранировании = уязвимость не закрыта.
- Если защита (auth-секрет, middleware, RBAC-фильтр) применена к одному эндпоинту/сервису — проверь ВЕСЬ класс однотипных эндпоинтов/сервисов. Точечный фикс без покрытия всего класса — это не фикс, а иллюзия фикса. Ищи "братьев и сестёр" уязвимого паттерна по всей кодовой базе (grep по сигнатуре, а не по имени функции).
- Если в коде есть RBAC/switch/if-else по ролям — всегда проверяй ветку "иначе" (default case). Отсутствие else-ветки с явным отказом в доступе — это разрешение по умолчанию, то есть дыра.
- Не принимай объяснение "это устаревшая версия" или "это уже поправлено"
без самостоятельной проверки текущего состояния репозитория. Если раньше
был отчёт с найденными рисками — перепроверь каждый пункт по текущему
коду, независимо от того, что утверждает команда. Начни сверку с
docs/bugs/security_audit/, а не с чистого листа, и прогониscripts/verify_audit_fixes.pyдля регрессионной проверки, если он есть. Если новая находка фактически совпадает с уже трекнутым и осознанно принятым там риском (например, отключённый networkPolicy, одна реплика для HA-компонента) — сошлись на существующий файл вместо дубликата, и отметь отдельно только если текущее изменение делает риск хуже, чем он был зафиксирован. - Формулируй разницу между статусами явно: "не исправлено" / "исправлено формально (код есть, защиты нет)" / "исправлено выборочно (часть класса покрыта)" / "исправлено полностью" / "новая находка".
МЕТОДОЛОГИЯ: ТРИ НЕЗАВИСИМЫХ СРЕЗА
Проведи аудит тремя независимыми методами и не позволяй одному срезу подменять другой — у них разная слепая зона.
СРЕЗ 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, независимая проверка закрытия предыдущих находок (не по самоотчёту команды).
- Небезопасные значения по умолчанию как системный паттерн (если один флаг выключен по умолчанию — проверь, не системная ли это практика: другие флаги/фичи безопасности в проекте тоже выключены по умолчанию?).
ДЕТАЛЬНЫЙ ЧЕК-ЛИСТ ПО КАТЕГОРИЯМ
Аутентификация и авторизация
- Все ли эндпоинты, требующие аутентификации, её действительно проверяют (нет ли "забытых" открытых маршрутов, особенно /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.
Мультитенантность (изоляция между компаниями-клиентами) — это SaaS CRM с несколькими компаниями-клиентами на общей инфраструктуре; утечка данных МЕЖДУ компаниями тяжелее по последствиям, чем IDOR внутри одной компании (регуляторный риск, доверие сразу всех клиентов платформы), поэтому разбирай отдельно от общего IDOR-пункта выше, а не как его частный случай.
- Для КАЖДОЙ точки чтения/записи данных (REST-хендлер, WebSocket- подписка, кэш-ключ, поисковый индекс, очередь событий, экспорт/отчёт) — фильтруется ли она по company_id/tenant_id на уровне запроса к БД (WHERE company_id = ...), а не только проверкой на уровне UI/роутера.
- Совпадение company_id проверяется явно (сравнение значения из токена/контекста с company_id самой записи), а не подразумевается тем, что "запрос и так идёт из авторизованной сессии".
- Массовые операции, экспорт, аналитика/дашборды — не пересчитывают ли они агрегаты по всем компаниям вместо своей.
- Общие ресурсы между сервисами (Redis-ключи, RabbitMQ-очереди, файловое хранилище) — не может ли ключ/имя коллизировать между разными компаниями при одинаковых внутренних ID (например, contact_id уникален внутри компании, но не глобально).
WebSocket / realtime
- Проверяется ли токен/роль/company_id при установке соединения (connect), И отдельно — при каждой подписке на канал/комнату/диалог (join), а не только один раз на connect.
- Может ли клиент подписаться на чужой канал, подставив/угадав room-id, dialog-id, user-id, если сервер не сверяет владельца канала с текущим пользователем.
- Рассылка событий (broadcast) — фильтруется ли получатель по company_id/роли перед отправкой, или сервер полагается на то, что клиент "просто не подписан" на чужие данные.
Internal-API между сервисами
- Пройдись по ВСЕМ
/internal/*эндпоинтам во ВСЕХ сервисах и построй таблицу: сервис | эндпоинт | требует ли shared-secret/mTLS | проверяется ли этот секрет фактически (а не только объявлен в переменных окружения). Ищи расхождения — один и тот же класс операций (send-message, delete-by-id, wipe-data, sync) защищённый в одном сервисе и незащищённый в соседнем — это системная дыра. - Может ли internal-эндпоинт быть вызван напрямую снаружи кластера (нет ли дополнительного network-level ограничения, если auth слабый)?
- Пройдись по ВСЕМ
Инъекции (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-запроса напрямую.
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 из тела вебхука?
XSS (включая Stored XSS в клиентских виджетах)
- Любое использование innerHTML/dangerouslySetInnerHTML/document.write с недоверенными данными.
- Встраиваемые на сторонних сайтах виджеты — это код, исполняющийся в браузере конечных посетителей сайтов ваших клиентов. Уязвимость там имеет более широкий радиус поражения, чем внутренняя XSS — квалифицируй с учётом этого при оценке severity.
- CSP (Content-Security-Policy) настроен ли и достаточно ли строг.
- Clickjacking: заголовки
X-Frame-Options/frame-ancestors— предотвращают ли встраивание основного приложения (не виджета) в чужой iframe.
Работа с секретами и 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-вывод конфига при старте сервиса).
Загрузка и хранение файлов
- Проверка MIME-типа и расширения при загрузке (не доверять Content-Type от клиента без валидации содержимого).
- Ограничение размера файла, защита от zip-бомб/decompression bomb для архивов.
- Публичные эндпоинты раздачи файлов (/public/documents и т.п.) — требуют ли аутентификации, если файлы содержат PII или приватные данные?
- Path traversal при формировании пути сохранения/чтения файла из пользовательского ввода.
- Object storage (S3/MinIO): публичность бакетов, версионирование, репликация.
Зависимости и суплай-чейн
- Полная разбивка уязвимостей по критичности и по сервисам (не общая цифра, а по каждому сервису отдельно — где сосредоточен риск).
- Совпадающие критичные библиотеки, используемые в нескольких сервисах разных версий (например, разные версии одного фреймворка в разных сервисах — означает, что патч придётся катить 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, где одноимённый публичный пакет мог бы их подменить.
Docker / контейнеры
- USER указан (non-root) в каждом Dockerfile — построй таблицу по всем образам.
- readOnlyRootFilesystem, drop: ALL capabilities, allowPrivilegeEscalation: false в securityContext.
- Секреты не передаются через ARG/ENV в Dockerfile (попадают в историю слоёв).
- Multi-stage build для исключения build-инструментов и dev-зависимостей из финального образа.
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-находок, но не игнорируй.
- Стратегия бэкапов БД — задокументирована и автоматизирована ли.
Обработка ошибок и наблюдаемость
- Паттерн "молчаливого проглатывания" ошибок (broad except с логированием и возвратом None/пустого результата без re-raise/ алерта) — маскирует ли это сбои безопасности (например, неудавшуюся проверку авторизации, которая по ошибке трактуется как "разрешено")?
- Логируются ли security-события (неудачные попытки авторизации, изменение ролей, массовые удаления) отдельно и доступны ли для мониторинга/алертинга.
- Утечка внутренней информации через сообщения об ошибках (стектрейсы, версии библиотек, структура БД) в ответах API наружу.
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 без прямого сценария эксплуатации на момент аудита (например, отсутствующий заголовок безопасности без известного вектора атаки в текущей архитектуре).
Для каждой находки указывай не только итоговый уровень, но и кто может эксплуатировать (аноним / аутентифицированный юзер / только внутренняя сеть) и что теряется (чтение / запись / полный компромисс) — это и есть обоснование уровня.
ФОРМАТ ОТЧЁТА
- Executive summary (для руководства, без технического жаргона): что критично, что рискует бизнесом/репутацией/регуляторикой, что делать в первую очередь.
- Таблица KPI: число critical/high/medium/low находок, число уязвимостей зависимостей по критичности, % контейнеров под non-root, число незакрытых рисков из предыдущего отчёта (если это повторный аудит).
- Если это повторный аудит — таблица сопоставления "пункт предыдущего отчёта → текущее состояние (file:line) → статус (не исправлено / формально / выборочно / исправлено)". Не принимай прошлые объяснения без перепроверки.
- Раздел "исправлено, но не работает" отдельно — это самый показательный сигнал о зрелости процесса, выделяй его явно.
- Полный список находок с привязкой file:line, конкретным сценарием эксплуатации, severity (CVSS-подобная оценка или critical/high/medium/low) и рекомендацией.
- Раздел "что сделано хорошо" — сильные паттерны в кодовой базе, которые стоит тиражировать, а не переделывать. Аудит без баланса теряет доверие и её сложнее использовать для мотивации команды.
- План действий по срокам: 24-48 часов (эксплуатируемые сегодня векторы), 1 неделя (остальные critical), 2-4 недели (процесс и архитектура), решения уровня руководства (владелец безопасности, независимая переверификация, архитектурные решения, которые нельзя решить точечными патчами).
- Раздел "методология и ограничения покрытия" — какие инструменты использовались, какие директории/сервисы НЕ были просканированы и почему, чтобы отсутствие находок в непокрытой зоне не читалось как "там всё чисто".
ПРАВИЛА ОФОРМЛЕНИЯ НАХОДОК
Для каждой находки обязательны:
- Стабильный ID находки (например,
SEC-2026-08-04-001) — чтобы при повторном аудите можно было сослаться на конкретную находку по ID, а не пересказывать её заново своими словами (пересказ может незаметно "уехать" от исходной формулировки и сломать сопоставление статусов между аудитами). - Путь к файлу и номер строки (или диапазон).
- Название уязвимости и категория (можно сослаться на OWASP Top 10 / OWASP API Security Top 10 / CWE).
- Конкретный сценарий эксплуатации: "если сделать запрос X с параметром Y, система вернёт/сделает Z" — не абстрактные формулировки вроде "может быть уязвимость".
- Severity с обоснованием (кто может использовать: аутентифицированный пользователь / любой внешний / только внутренняя сеть; что теряется: чтение данных / запись / полный компромисс).
- Статус относительно предыдущего аудита, если применимо.
- Рекомендация по исправлению — конкретная (не "улучшить безопасность", а "добавить else-ветку с явным отказом", "включить флаг X по умолчанию", "заменить f-string на параметризованный запрос").
ЗАПУСК АУДИТА (практическая инструкция)
- Определи периметр: перечисли все сервисы (директории верхнего уровня в
services/), фронтенд-приложения, встраиваемые виджеты/расширения, инфраструктурные конфиги. - Прочитай реестр прошлых находок в
docs/bugs/security_audit/ПЕРЕД началом ручного разбора, если он есть, — это готовый источник уже известных проблем, не дублируй работу, а проверь, устранены ли они. - Запусти автоматизированные инструменты СРЕЗА 1 по каждому сервису/образу/чарту, где это возможно в текущем окружении, сохрани сырой вывод для приложений к отчёту. Отфильтруй заведомые false positive (тестовые фикстуры, placeholder-значения вида "changeme"/"example_key") явным списком в разделе ограничений, а не молча — чтобы было видно, что они рассмотрены, а не пропущены.
- Раздели ручной разбор СРЕЗА 2 на независимые куски (по сервису/зоне) — если доступен Agent tool, запусти несколько независимых субагентов на разные зоны параллельно (в foreground, если результат нужен сразу в этом диалоге), чтобы не пропустить объём и не дать одному агенту "срезать угол" по всей кодовой базе разом. Кодовая база крупная (десяток+ сервисов) — каждому субагенту передай конкретный список файлов/директорий его зоны и применимые разделы этого скилла (чек-лист, шкалу severity, формат находки), а не пересказ своими словами. Записывай подтверждённые находки в промежуточный файл сразу по мере разбора каждой зоны, а не держи их только в контексте до финального отчёта: при сжатии длинного диалога ранее найденное иначе может потеряться.
- Проведи архитектурный обзор СРЕЗА 3 отдельно, независимо от результатов среза 2.
- Сведи все три среза в единый отчёт по формату выше, убери дубликаты, но не объединяй находки разной природы (secret-scanner нашёл файл ≠ ручной разбор подтвердил, что секрет реальный и активный — фиксируй оба факта, если они есть).
- Если это повторный аудит — обязательно перепроверь КАЖДЫЙ пункт предыдущего отчёта по текущему состоянию кода, а не полагайся на статус, заявленный командой.
- Явно укажи, какие проверки НЕ были выполнены (ограничения окружения, нет доступа к прод-секретам, нет доступа к рантайм-логам и т.п.) — это часть честного отчёта, а не его слабость.
- Сохрани финальный отчёт файлом в
docs/bugs/security_audit/(например,full-audit-<дата>.md) — это то же место, где хранится реестр прошлых находок, и следующий повторный аудит должен его найти при сверке.
Это аудит, не имплементация: правки вносит разработчик по итогам отчёта, не ты в рамках этого скилла.