Аудит безопасности кода с Vibe Codex
Хороший security-аудит — это не «найди дыру», а «покажи, какие классы проблем здесь физически невозможны».
Вес security-проблемы редко зависит от изощрённости — обычно это банальный SQL-конкатенат, незахешированный токен или забытый http.Get(userInput). Vibe Codex эти паттерны ловит охотно, потому что они шаблонны. Сложные дыры остаются человеку — но и тут ассистент сужает поиск.
Команда одной строкой
$ vibe-codex audit security --scope ./src
[opus] Сканирую 12 380 файлов...
[opus] 7 находок (3 high, 2 medium, 2 low):
HIGH src/billing/PaymentController.java:42
SQL injection — конкатенация userId в строку запроса
HIGH src/api/upload.py:88
SSRF: requests.get(user_url) без allowlist
HIGH src/auth/Token.go:112
SHA-1 для подписи токенов
MEDIUM src/admin/views.py:25
IDOR: нет проверки ownership на GET /docs/<id>
MEDIUM src/integration/SapClient.kt:74
XML без отключения внешних entities — XXE
LOW src/utils/RandomId.java:14
java.util.Random для генерации session-id
LOW .env.example
выглядит как реальный ключ, проверьте
Паттерн №1. SQL-инъекции
Самая частая находка. Vibe Codex ищет конкатенации строк в SQL, использование %s с user input, format-функции в запросах.
// найдено
@GetMapping("/payments/{userId}")
public List<Payment> list(@PathVariable String userId) {
return jdbcTemplate.query(
"SELECT * FROM payments WHERE user_id = " + userId,
rowMapper
);
}
// предлагаемая правка
return jdbcTemplate.query(
"SELECT * FROM payments WHERE user_id = ?",
rowMapper,
Long.parseLong(userId)
);
Паттерн №2. SSRF
Бэкенд, который ходит по URL из тела запроса, — это SSRF, пока не доказано обратное. Ассистент подсветит и предложит allowlist или whitelist + SOCKS-прокси.
# найдено
@app.post('/preview')
def preview(url: str):
return requests.get(url).text
# предлагаемая правка
ALLOWED_DOMAINS = {'images.acme.ru', 'cdn.acme.ru'}
@app.post('/preview')
def preview(url: str):
parsed = urlparse(url)
if parsed.scheme not in {'https'}:
raise HTTPException(400, 'https only')
if parsed.hostname not in ALLOWED_DOMAINS:
raise HTTPException(400, 'domain not allowed')
return requests.get(url, timeout=5,
allow_redirects=False).text
Паттерн №3. Криптография «своими руками»
SHA-1, MD5, плоский XOR «для скрытия токена», CBC без HMAC, Math.random() для session-id. Список классики, который не меняется десять лет.
// найдено
func signToken(uid string) string {
h := sha1.New()
h.Write([]byte(uid + secret))
return hex.EncodeToString(h.Sum(nil))
}
// предлагаемая правка
func signToken(uid string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(uid))
return hex.EncodeToString(mac.Sum(nil))
}
«Хороший аудитор не объясняет, почему MD5 это плохо. Он показывает, на что заменить».
Паттерн №4. IDOR
Endpoint GET /documents/<id> без проверки, что текущий пользователь владеет документом. Очень частый баг в API-фастлайт.
# найдено
def get_doc(doc_id: int, user: User):
return Document.objects.get(id=doc_id)
# предлагаемая правка
def get_doc(doc_id: int, user: User):
return Document.objects.get(id=doc_id, owner_id=user.id)
# или сначала запрос, потом явная проверка:
# if doc.owner_id != user.id: raise PermissionDenied
Паттерн №5. Секреты в репозитории
Ассистент ищет «похожее на ключ»: 32-символьные строки в hex, JWT-формат, AWS-форматы, BEGIN PRIVATE KEY. Не «помогает выйти на GitHub Secret Scanning», а сам сообщает в pre-commit, что в diff поехал ключ.
$ git commit -m "wip"
[pre-commit] vibe-codex security:
WARN config/local.yml:14 looks like an API key
(entropy 4.8, format /^[A-Za-z0-9]{40}$/)
[pre-commit] commit aborted. fix or pass --allow-secret
Что ассистент НЕ делает
- Не отправляет код в третьи системы для сканирования. Аудит — локально + LLM-вызов через ваш роутер.
- Не пишет эксплойты. Может объяснить класс уязвимости, но PoC — нет.
- Не «лечит без анализа». Сначала описывает риск, потом предлагает правку.
- Не подменяет SAST. Это complement, а не replace.
Ритуал недели
Раз в неделю — на pre-merge или в Friday-deploy gate — запускается полный аудит:
vibe-codex audit security --since=7d --format=sarif > audit.sarif
Результат — SARIF, который кладётся в GitHub Code Scanning или импортируется в Defect Dojo. Дальше — обычный workflow безопасников: тикеты, фиксы, ревалидация.
Граница ответственности
Vibe Codex — это инструмент, который снимает с инженера 80% рутины security-обзора. 20% остаются человеку: бизнес-логические уязвимости (race на бонусы, fraud-сценарии), архитектурные ошибки (доверие между сервисами), human-эксплойты. Их не находит ни один скан, потому что они не паттерны.
Идея простая: пусть рутина уходит ассистенту, а интересное — людям. Так и работает security в нормальной команде.
Готов попробовать?
brew tap xrouter-chat/tap && brew install vibe-codex — и за 30 секунд ты в деле.
Поставить Vibe Codex →