Короткий ответ
До запуска проверь не весь интернет, а пять конкретных границ.
Убедись, что вход нельзя перебирать без ограничений, секреты не лежат в коде и логах, каждый объект защищён серверной авторизацией, SQL не собирается из пользовательских строк, а установка зависимостей не запускает непроверенный код. Такой аудит не доказывает абсолютную безопасность, но быстро находит ошибки с самым большим радиусом поражения.
Результат за один проход
- Карта пяти зон риска с доказательствами из файлов проекта.
- Негативные тесты для входа, доступа к объектам и запросов к базе.
- План действий, если токен уже попал в репозиторий или лог.
- Готовый промпт, который сначала просит Claude провести аудит, а не переписывать проект.
00 · Граница
Это предрелизная проверка, а не сертификат безопасности.
Безопасность удобно обсуждать конкретными сценариями. Может ли один пользователь получить чужой отчёт, заменив report_id? Может ли бот сделать тысячу попыток входа? Выполняет ли npm install неизвестный shell-скрипт? Попадает ли ключ модели в клиентский JavaScript?
Начни с карты: браузер, API, база, хранилище файлов, очередь, AI-провайдер, платёжный сервис и панель администратора. Для каждой стрелки запиши, какие данные идут, кто имеет доступ и чем проверяется право. Если сам проект ещё не разделён на такие зоны, сначала пригодится карта ролей AI-сервиса. OWASP ASVS можно использовать как более полный набор технических требований после первого прохода. [6]
Как пользоваться гайдом. Создай отдельную задачу на релиз и проходи пункты по одному. Для каждого пункта сохрани три вещи: найденный факт, уровень риска и доказательство исправления. «Посмотрели код — вроде нормально» не считается доказательством. Им может быть автоматический тест, скрин настройки без секретов, ссылка на конкретную строку кода или запись из журнала тестового запуска.
01 · Вход
Ограничь попытки входа и защити восстановление доступа.
Форма входа выглядит маленькой, но за ней находятся пароли, сессии и административные права. Первый тест прост: отправь серию неверных попыток для одной учётной записи и с разных адресов. Сервис должен замедлять или ограничивать повторные попытки, а не бесконечно отвечать с одинаковой скоростью. OWASP отдельно описывает login throttling и осторожное применение временной блокировки. [1]
Проверяй не только /login. В тот же контур входят регистрация, сброс пароля, подтверждение почты, выдача одноразового кода и обновление токена. Ответы не должны помогать перечислять существующие аккаунты. Фраза «если такой адрес есть, мы отправили письмо» раскрывает меньше, чем разные ответы для существующего и неизвестного email.
| Проверка | Ожидаемый результат | Доказательство |
|---|---|---|
| Много неверных попыток | Задержка, лимит или временная блокировка без вечной блокировки аккаунта | Интеграционный тест и метрика срабатываний |
| Неизвестный email | Ответ не подтверждает наличие аккаунта | Сравнение статуса, текста и времени ответа |
| Администратор | MFA — второй фактор входа — и отдельная проверка роли | Тест входа без второго фактора |
| Сброс пароля | Одноразовая ссылка с ограниченным сроком | Повторное использование завершается отказом |
Как проверить руками. Не атакуй публичный сервис и не используй чужие аккаунты. На тестовом окружении заведи две свои учётные записи. Несколько раз введи неверный пароль, запроси сброс для существующего и несуществующего адреса, повторно открой уже использованную ссылку сброса. Затем проверь, что лимит действует не только в браузере: тот же запрос из API-клиента тоже должен быть ограничен сервером.
02 · Секреты
Секрет не должен жить там, откуда его легко скопировать.
API-ключ модели, пароль базы, секрет проверки webhook и ключ подписи сессии нельзя помещать в исходники, клиентскую сборку, Dockerfile, пример запроса, скриншот или обычный лог. Файл .env удобен локально, но это не делает его безопасным хранилищем для продакшна. В рабочей среде секрет передаётся через систему секретов или защищённые настройки платформы, имеет минимальный scope — только необходимый набор разрешений — и может быть отозван отдельно. Эти принципы совпадают с рекомендациями OWASP по жизненному циклу, минимальным правам, аудиту и ротации секретов. [4]
Проверь три поверхности. В Git ищи не только текущие файлы, но и историю. Во frontend bundle — готовых JavaScript-файлах, которые сервер отдаёт браузеру, — ищи значения, которые не должен получить посетитель. В логах проверь маскирование заголовков Authorization, cookies, строк подключения и тел запросов. GitHub secret scanning умеет искать известные форматы учётных данных в истории, но не распознает любой внутренний секрет, поэтому автоматический поиск не заменяет ревью. [7]
Что считать успехом. В репозитории находятся только названия переменных и безопасные примеры-заглушки. Настоящее значение доступно лишь тому серверному процессу, которому оно нужно. У тестового и боевого окружения разные ключи. Для каждого секрета записано, где его отозвать, кто это может сделать и какие сервисы потребуется обновить после ротации.
04 · Данные
Передавай значения отдельно от текста SQL.
Опасная конструкция склеивает запрос и ввод пользователя в одну строку. Безопасная конструкция использует prepared statement или параметры ORM, чтобы база различала код и данные. OWASP называет параметризованные запросы основным способом предотвращения SQL injection и отдельно предупреждает против конкатенации пользовательского ввода. [5]
// Плохо: строка пользователя меняет структуру запроса
"SELECT * FROM reports WHERE owner = '" + userInput + "'"
// Принцип безопасного варианта
query("SELECT * FROM reports WHERE owner = ?", [userInput])
Параметры не всегда подходят для имён колонок, таблиц и направления сортировки. В этих местах пользовательский выбор нужно сопоставить с коротким allowlist из кода. Например, sort=created превращается в заранее заданное имя created_at, а неизвестное значение отклоняется. ORM помогает, но raw-методы, шаблонные строки и динамические фильтры всё равно нужно искать отдельно.
Как проверять. Сначала найди в коде все места с сырым SQL, конкатенацией строк и форматированием запросов. Затем для каждой формы, фильтра, поиска и сортировки проверь, что пользовательское значение уходит параметром. Не пытайся доказывать защиту одной «магической» строкой атаки: важнее увидеть конструкцию запроса и закрепить её тестом, который ломается при возврате к склейке строк.
05 · Установка
До npm install прочитай, какой код он собирается выполнить.
В npm lifecycle есть preinstall, install, postinstall и prepare. Эти команды могут запускаться во время установки проекта или зависимости. Поэтому незнакомый репозиторий сначала изучают статически, а потом запускают в изолированной среде без реальных секретов. [9]
Первый проход: открой package.json, lock-файл, shell-скрипты, workflow-файлы и зависимости из git, URL или локальных путей. Флаг --ignore-scripts отключает package scripts во время установки, но явный npm run всё равно запускает выбранный скрипт. Это средство первого осмотра, а не универсальная песочница. [10]
Для этой зоны есть отдельный пошаговый маршрут: как проверить GitHub-репозиторий до npm install. Он полезен до того, как код оказался в основном проекте.
Инцидент · Токен раскрыт
Не начинай с удаления файла. Сначала останови действие секрета.
- Шаг 1
Отзови или ротируй токен.
Считай секрет скомпрометированным. Создай новый только после отзыва старого и выдай ему минимальные права. GitHub прямо рекомендует ротацию как первый шаг. [8]
- Шаг 2
Оцени использование.
Проверь логи провайдера, неожиданные запросы, расходы, входы и изменения конфигурации. Зафиксируй время возможной экспозиции.
- Шаг 3
Замени секрет во всех потребителях.
CI — автоматическая сборка и тесты, продакшн, тестовое окружение, локальные машины и фоновые процессы могут использовать разные копии одного значения.
- Шаг 4
Удали секрет из кода и истории.
Обычный новый commit не стирает старое значение из истории. Очистка истории затрагивает клоны, ветки, ответвления репозитория и запросы на слияние, поэтому её нужно планировать отдельно. [8]
- Шаг 5
Закрой причину повторения.
Добавь secret scanning, pre-commit проверку, маскирование логов и документированную процедуру ротации.
Артефакт · Пять проверок
Чек-лист, который можно положить в release issue.
| Зона | Pass | Доказательство | Стоп-сигнал |
|---|---|---|---|
| Вход | Есть ограничение попыток и защищённый reset | Негативные интеграционные тесты | Вход можно перебирать без замедления |
| Секреты | Нет значений в Git, браузерной сборке и логах | Скан истории и собранного интерфейса | Реальный ключ найден хотя бы в одном месте |
| Авторизация | Проверяется роль и конкретный объект | Матрица ролей и тест пользователь A/B | Чужой ID открывает данные |
| SQL | Значения параметризованы, варианты ограничены разрешённым списком | Ревью сырого SQL и тесты ввода | Ввод склеивается с запросом |
| Установка | Установочные этапы и источники зависимостей изучены | Зафиксированный commit, lock-файл, журнал проверки | Непонятный скрипт запускается при установке |
Для системного security review расширь список требованиями ASVS, релевантными архитектуре и уровню риска проекта. [6]
Промпт для Claude
Сначала аудит и план. Изменения только после подтверждения.
Скопируй текст ниже или скачай промпт в Markdown. Если используешь Claude Code, начни с режима plan и ограничь инструменты чтением. В CLI есть отдельные настройки режима разрешений и списков доступных инструментов. [11]
Работай как технический аудитор. Сначала только изучи проект и составь отчёт. Не меняй файлы, конфигурацию, зависимости, инфраструктуру и данные без моего отдельного подтверждения.
Не проси и не выводи реальные ключи, пароли, cookies, токены, строки подключения и персональные данные. Не запускай install-скрипты, миграции, deploy, seed и внешние запросы.
Проверь пять зон: защита входа; хранение и ротация секретов; серверная авторизация на каждый объект; параметризованный SQL; package lifecycle и источники зависимостей.
Для каждого вывода укажи файл и строку. Верни карту поверхности атаки, таблицу рисков, безопасный план исправлений, тесты перед релизом и зоны, где нужен специалист. После отчёта остановись и запроси подтверждение.
FAQ
Частые вопросы перед проверкой безопасности.
Можно ли просто отправить весь репозиторий Claude и довериться отчёту?
Нет. AI хорошо помогает найти подозрительные места и составить план, но может пропустить путь выполнения, неверно понять настройки инфраструктуры или придумать несуществующую защиту. Проси ссылки на файлы и строки, а критичные выводы подтверждай тестом или специалистом. Перед отправкой убери реальные секреты и пользовательские данные.
Если ключ лежал в приватном репозитории, его всё равно менять?
Да, если нельзя доказать, что доступ к истории был строго ограничен и ключ никто не мог скопировать. Практичнее считать раскрытый секрет скомпрометированным: сначала отозвать, затем создать новый. Простое удаление файла не прекращает действие старого ключа.
Rate limit полностью защищает пароль от перебора?
Нет. Ограничение попыток уменьшает скорость атаки, но рядом нужны безопасное хранение паролей, защита сброса, второй фактор для важных ролей, контроль утечек сессий и мониторинг аномалий.
Достаточно ли ORM, чтобы забыть про SQL injection?
Нет. ORM обычно параметризует стандартные операции, но сырой SQL, динамические имена колонок, сортировки и самописные фильтры могут снова соединить код с пользовательской строкой. Эти места проверяются отдельно.
Когда нужен настоящий security-аудитор?
До запуска платежей, сложного административного доступа, чувствительных данных, корпоративного SSO, массовых загрузок или автономного AI с правом выполнять действия. Пять точек из статьи — хороший минимальный барьер, но не замена модели угроз и профессиональному тестированию системы высокого риска.
Следующий шаг
Закрой сначала самый опасный доказанный риск.
Не превращай аудит в коллекцию замечаний. Для каждого критичного вывода должны появиться владелец, исправление и тест, который не даст ошибке вернуться. После этого повтори негативные сценарии и только затем открывай продакшн-трафик.
