# Как проверить код от Cursor и Claude Code на уязвимости: сканеры безопасности для ИИ-проектов

> AI Release · @ai_release1 · https://ai-release.org/guides/kak-proverit-kod-ot-cursor-i-claude-code-na-uyazvimosti.html

## TL;DR
- Время выполнения: 40–60 минут на один репозиторий среднего размера.
- Уровень сложности: Intermediate.
- Понадобится: `git`, `python3` + `pip` (для Semgrep, Bandit, pip-audit), Node.js + `npm`, `gitleaks`, `trivy`, `jq`. Docker — опционально. Точные версии пакетов и минимальные требования сверьте с документацией каждого инструмента.
- Результат: папка `reports/` с четырьмя файлами SARIF/JSON, список находок, отсортированный по критичности, и pre-commit-хук, который блокирует коммит с секретом.

## Требования и подготовка
![Иллюстрация к разделу «Требования и подготовка»](https://ai-release.org/guides/img/kak-proverit-kod-ot-cursor-i-claude-code-na-uyazvimosti-ru-1.jpg)


- ОС: Linux/macOS, либо Windows 10/11 с WSL2 — часть сканеров ставится скриптом установки.
- Права: возможность ставить пакеты (`pip install --user` или виртуальное окружение) и писать в `.git/hooks`.
- Свободное место: от 1–2 ГБ (Trivy скачивает локальную базу уязвимостей; размер сверьте в документации).
- Репозиторий с кодом, созданным в Cursor или Claude Code, под управлением git.
- API-ключи для сканеров не нужны, если вы используете локальные правила Semgrep и файловый режим Trivy.

Три класса риска, которые проверяются разными инструментами:

| Класс проблемы | Инструмент | Что ищет | Куда смотрит |
|---|---|---|---|
| Секреты в коде | `gitleaks` | API-ключи, токены, пароли — включая историю коммитов | `.git`, рабочая копия, staged-файлы |
| Уязвимые зависимости | `trivy`, `npm audit`, `pip-audit`, `osv-scanner` | CVE (известные уязвимости) в сторонних пакетах | `package-lock.json`, `requirements.txt`, lock-файлы |
| Опасные паттерны в коде | `semgrep`, `bandit` | инъекции, `eval`, отключённая проверка TLS, небезопасные вызовы | исходники `.py`, `.js`, `.ts` и др. |

SAST — статический анализ исходников без запуска программы. SCA — анализ состава зависимостей (какие версии библиотек вы подключили и есть ли в них CVE).

Установка и быстрая проверка, что бинарники на месте:

```bash
python3 -m pip install --user semgrep bandit pip-audit
gitleaks version
trivy --version
semgrep --version
```

**Пример:** вывод `gitleaks version` — строка вида `8.x.x`; если команда не найдена, бинарник не в `PATH` (решение — в разделе проблем).

Чек-лист перед стартом:

- [ ] репозиторий склонирован, `git status` чистый
- [ ] создана ветка `security/ai-code-audit`
- [ ] есть папка `reports/` и она в `.gitignore`
- [ ] `gitleaks version`, `trivy --version`, `semgrep --version` отвечают
- [ ] известен менеджер пакетов проекта (`npm` или `pip`)

Работа со сканерами удобно ложится на ветки: если вы применяете `git` или `jujutsu` для ИИ-агентов, посмотрите разбор [Jujutsu или Git: что выбрать для работы с ИИ-агентами и Claude Code](https://ai-release.org/guides/jujutsu-ili-git-chto-vybrat-dlya-raboty-s-ii-agentami-i.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide).

## Шаг 1. Зафиксировать точку отсчёта и собрать инвентарь зависимостей

**Что сделать:** создать отдельную ветку, исключить из коммита секреты и составить список файлов, описывающих зависимости.

**Зачем:** сканеры читают ровно эти файлы. Если `requirements.txt` или `package-lock.json` нет, SCA-проверка покажет ноль находок — не потому что всё чисто, а потому что нечего анализировать.

```bash
git checkout -b security/ai-code-audit
mkdir -p reports
printf 'reports/\n.env\n.env.*\n' >> .gitignore
```

Сбор инвентаря:

```bash
find . -name "package.json" -not -path "*/node_modules/*" -not -path "*/.git/*"
find . -name "requirements*.txt" -o -name "pyproject.toml" -not -path "*/.git/*"
```

**Пример:** вывод первой команды — `./frontend/package.json`, вывод второй — `./backend/requirements.txt`. Это значит, что проверять зависимости нужно в двух местах.

**Как проверить:** `git status` показывает ветку `security/ai-code-audit` и изменения только в `.gitignore`. `ls reports` не выдаёт ошибку.

Дальше зафиксируйте, что именно сгенерировала модель — это ускорит разбор находок:

```bash
git log --oneline -20
```

Почему это работает: сканеры выдают путь и номер строки, а по истории коммитов вы за пару секунд понимаете, какой промпт и какой агент породили проблемный файл.

## Шаг 2. Прогнать три группы сканеров и сохранить отчёты
![Иллюстрация к разделу «Шаг 2. Прогнать три группы сканеров и сохранить отчёты»](https://ai-release.org/guides/img/kak-proverit-kod-ot-cursor-i-claude-code-na-uyazvimosti-ru-2.jpg)


**Что сделать:** последовательно запустить поиск секретов, проверку зависимостей и SAST, каждый отчёт — в файл.

**Зачем:** без файла результат живёт только в терминале и теряется после прокрутки. SARIF — стандартный формат отчётов, его понимают интерфейсы code review и CI.

### 2.1 Секреты

```bash
gitleaks detect --source . --redact --report-format json --report-path reports/gitleaks.json
```

`--redact` прячет сам секрет в выводе, чтобы он не попал в логи и скриншоты.

**Пример:** строка отчёта `leaks found: 1`, затем путь `backend/.env.example:12`. Даже пример конфига с реальным ключом — это утечка.

### 2.2 Зависимости

Для Node.js:

```bash
npm audit --audit-level=high --json > reports/npm-audit.json
```

Для Python:

```bash
pip-audit -r backend/requirements.txt --format json --output reports/pip-audit.json
```

Универсальный вариант по всему проекту:

```bash
trivy fs --scanners vuln,secret,misconfig --format sarif --output reports/trivy.sarif .
```

`misconfig` дополнительно проверяет Dockerfile и конфиги на небезопасные настройки. Синтаксис флагов в разных версиях Trivy отличается — сверьтесь с документацией, если команда не принимает `--scanners`.

### 2.3 SAST по исходникам

```bash
semgrep --config auto --metrics=off --sarif --output reports/semgrep.sarif .
bandit -r backend -f json -o reports/bandit.json
```

`--config auto` подтягивает публичный набор правил; `--metrics=off` отключает отправку телеметрии. Bandit работает только по Python и ловит `eval`, `subprocess` с `shell=True`, `assert` в продакшн-коде.

**Как проверить:** `ls -1 reports/` показывает `gitleaks.json`, `npm-audit.json`, `pip-audit.json`, `trivy.sarif`, `semgrep.sarif`, `bandit.json`.

Почему это работает: каждый сканер смотрит на свой слой — текст файлов, список версий пакетов, дерево вызовов. ИИ-ассистент чаще всего ошибается именно в шаблонах: конкатенация SQL-строки, ключ прямо в коде «чтобы пример запустился», отключённая проверка сертификата. Эти три слоя как раз их и накрывают.

Если вы запускаете проверки руками много раз в день, имеет смысл вынести их в субагента Claude Code — схема описана в гайде [Claude Code для команды: как настроить субагентов и общий ИИ-суперагент](https://ai-release.org/guides/claude-code-dlya-komandy-kak-nastroit-subagentov-i-obsc.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide).

## Шаг 3. Проверить результат и встроить блокировку в коммит
![Иллюстрация к разделу «Шаг 3. Проверить результат и встроить блокировку в коммит»](https://ai-release.org/guides/img/kak-proverit-kod-ot-cursor-i-claude-code-na-uyazvimosti-ru-3.jpg)


**Что сделать:** прочитать агрегированный результат, разобрать коды возврата и поставить pre-commit-хук на секреты.

**Зачем:** сканер без хука запускают один раз. Хук превращает разовую проверку в постоянную.

Сводка по количеству находок:

```bash
jq '.runs[].results | length' reports/semgrep.sarif
jq '. | length' reports/npm-audit.json
```

**Пример:** `jq` вернул `3` для Semgrep — значит, в отчёте три находки; откройте файл и посмотрите поля `ruleId` и `startLine`.

Коды возврата дают машиночитаемый ответ:

```bash
gitleaks detect --source . --redact > /dev/null 2>&1; echo $?
```

**Как проверить:** `0` — чисто, `1` — есть находки, `2` — сканер упал (не смог скачать базу, битый конфиг). В разных инструментах значения кодов отличаются — сверьтесь с документацией, прежде чем строить на них CI.

Хук, который блокирует коммит с секретом:

```bash
cat > .git/hooks/pre-commit <<'EOF'
#!/bin/sh
gitleaks protect --staged --redact
EOF
chmod +x .git/hooks/pre-commit
```

**Пример проверки хука:** добавьте в файл строку `AWS_SECRET=test123` и выполните `git commit -m "test"` — коммит прервётся, в консоли появится путь к файлу и номер строки. Удалите строку, повторите — коммит проходит.

Итоговая таблица «что нашлось — что делать»:

| Находка | Приоритет | Действие |
|---|---|---|
| Ключ/токен в коде или истории | Критично | отозвать ключ у провайдера, затем вычистить из истории |
| CVE уровня high/critical в зависимости | Высокий | поднять версию пакета, пересобрать lock-файл |
| SQL-конкатенация, `eval`, `shell=True` | Высокий | переписать на параметризованный запрос / безопасный вызов |
| `misconfig` в Dockerfile (запуск от root) | Средний | добавить `USER` в Dockerfile |

Почему это работает: приоритет зависит не от «страшности» правила, а от того, можно ли проблему эксплуатировать снаружи. Ключ и CVE в публичном пакете — да; запуск от root внутри контейнера — только вместе с другой уязвимостью.

## Возможные проблемы и решения

**Проблема. Сканер не запускается после установки**

- Ошибка: `bash: semgrep: command not found`
- Причина: пакет установлен в пользовательский каталог или виртуальное окружение, которого нет в `PATH` в текущей сессии.
- Решение: выполните `python3 -m semgrep --version`. Если версия печатается — вызывайте сканер как `python3 -m semgrep --config auto .`, либо активируйте окружение: `source .venv/bin/activate` и повторите `semgrep --version`.

**Проблема. Trivy не может скачать базу уязвимостей**

- Ошибка: `FATAL failed to download vulnerability DB`
- Причина: нет доступа к сети, блокирующий прокси или закончилось место на диске.
- Решение: проверьте `df -h` и доступность сети, затем повторите `trivy fs --scanners vuln .`. Для офлайн-режима Trivy умеет работать с заранее скачанной базой — точные флаги и путь к кэшу сверьтесь с документацией.

**Проблема. Коммит блокируется из-за тестового ключа в примере конфига**

- Ошибка: в выводе `gitleaks protect` строка `leaks found: 1` и путь `backend/.env.example:12`, коммит прерван.
- Причина: правило сработало на демонстрационное значение, похожее на реальный ключ.
- Решение: замените значение на явный плейсхолдер (`API_KEY=<ваш-ключ>`) и закоммитьте. Если это осознанное исключение — добавьте путь в `.gitleaksignore` (формат файла сверьтесь с документацией). Если ключ когда-либо был настоящим — сначала отзовите его у провайдера, потом чистите историю.

## Резюме и следующие шаги
Три группы сканеров закрывают три разных слоя риска, а pre-commit-хук не даёт секрету вернуться в репозиторий. Следующий шаг — вынести те же команды в CI и повесить порог: сборка падает при находках уровня high и выше.

## FAQ

**Достаточно ли встроенной проверки Cursor и Claude Code?**
Нет. Ассистент подсказывает по контексту открытого файла и не сверяется с базой CVE и не строит полный список зависимостей. Встроенные предупреждения считайте частью ревью, а не аудитом; конкретный набор встроенных функций сверьте с документацией инструментов.

**Нужны ли платные аккаунты для этих сканеров?**
Для шагов из гайда — нет: gitleaks, Trivy, Semgrep с `--config auto`, Bandit, pip-audit и npm audit запускаются локально. Условия лицензий и границы бесплатных режимов сверьтесь с документацией каждого проекта.

**Что делать в первую очередь, если находок много?**
Сначала секреты — их нельзя «исправить позже», ключ нужно отозвать сразу. Затем зависимости уровня high/critical: обновление версии закрывает проблему без анализа кода. Паттерны в коде (SAST) разбирайте последними и по одному правилу за раз.

**Можно ли прогнать всё офлайн?**
Частично: Semgrep работает с локальным набором правил, Trivy — с заранее скачанной базой, gitleaks сети не требует. `npm audit` и установка пакетов требуют доступа к реестру. Точные офлайн-флаги сверьтесь с документацией.
