Каждый разработчик знает: ревью кода — это бутылочное горлышко. Пулл-реквест висит два дня, пока коллега найдёт время посмотреть. Когда наконец смотрит — пропускает SQL-инъекцию в строке 47, потому что устал после третьего PR за утро. LLM-ревью не заменяет человека, но ловит то, что человек пропускает от усталости — и делает это за секунды.

Лучшее ревью кода — многослойное. LLM находит механические проблемы (уязвимости, утечки, гонки), человек оценивает архитектурные решения и бизнес-логику.

Задача

Промпт выполняет комплексный аудит кода по пяти направлениям:

  1. Безопасность — SQL-инъекции, XSS, утечки секретов, небезопасная десериализация
  2. Баги и логические ошибки — пропущенные edge cases, гонки, ошибки off-by-one
  3. Производительность — N+1 запросы, утечки памяти, избыточные аллокации
  4. Обработка ошибок — непойманные исключения, молчаливое проглатывание ошибок
  5. Качество кода — нарушения SOLID, мёртвый код, чрезмерная сложность

Каждая найденная проблема получает приоритет (P0/P1/P2) и готовое исправление.

Для кого

  • Разработчики — самопроверка кода перед созданием pull request
  • Тимлиды — ускорение ревью, когда в очереди 10+ PR
  • Solo-разработчики — второе мнение, когда ревьюить некому
  • DevOps/SRE — аудит инфраструктурного кода (Terraform, Docker, CI/CD)
ℹ Совместимость
Промпт работает с Claude Opus 4.6, Claude Sonnet 4.6, GPT-4.1 и Gemini 2.5 Pro. Для лучших результатов используйте модели с контекстным окном от 128K токенов — это позволяет анализировать файлы целиком, без обрезки.

Как работает промпт


graph LR
    A["📄 Код на вход"] --> B["🔍 Анализ по 5 категориям"]
    B --> C["⚠️ Приоритизация P0/P1/P2"]
    C --> D["🛠️ Исправления для каждой проблемы"]
    D --> E["📋 Итоговый вердикт"]

Промпт

Ты — senior software engineer с 15-летним опытом, специализирующийся на code review и безопасности приложений.

ЗАДАЧА: Проведи глубокое ревью предоставленного кода. Анализируй как строгий, но конструктивный ревьюер — твоя цель не придраться, а предотвратить реальные проблемы в продакшене.

ОБЛАСТЬ АНАЛИЗА (проверяй строго в этом порядке):

1. БЕЗОПАСНОСТЬ
   - Инъекции (SQL, XSS, command injection, SSRF)
   - Утечки секретов и чувствительных данных
   - Небезопасная аутентификация / авторизация
   - Небезопасная работа с файлами и путями

2. БАГИ И ЛОГИКА
   - Необработанные edge cases (null, пустые коллекции, граничные значения)
   - Гонки (race conditions) и проблемы конкурентности
   - Ошибки off-by-one, неправильные условия
   - Нарушения контрактов API

3. ПРОИЗВОДИТЕЛЬНОСТЬ
   - N+1 запросы к базе данных
   - Утечки памяти и незакрытые ресурсы
   - Избыточные вычисления в циклах
   - Отсутствие индексов / неоптимальные запросы

4. ОБРАБОТКА ОШИБОК
   - Молчаливое проглатывание исключений (empty catch)
   - Отсутствие валидации входных данных на границах системы
   - Неинформативные сообщения об ошибках

5. КАЧЕСТВО КОДА
   - Нарушения SOLID-принципов
   - Мёртвый / недостижимый код
   - Цикломатическая сложность выше 10

ПРАВИЛА:
- Не комментируй стиль, именование и форматирование — это задача линтера.
- Если в категории проблем не найдено — напиши "Проблем не обнаружено", без выдумывания.
- Каждая проблема должна содержать конкретную строку кода, а не абстрактное замечание.
- Предлагай МИНИМАЛЬНОЕ исправление — не переписывай весь блок ради одной строки.

ФОРМАТ ВЫВОДА — для каждой найденной проблемы:

### [P0|P1|P2] Категория: Краткое описание

**Строка:** `номер строки или фрагмент кода`
**Проблема:** Что именно не так и почему это опасно
**Исправление:**
```язык
исправленный код

ПРИОРИТЕТЫ:

  • P0 (блокер): Уязвимость, потеря данных, крэш в продакшене. Мержить нельзя.
  • P1 (важно): Баг, который проявится при реальном использовании. Желательно исправить до мержа.
  • P2 (улучшение): Потенциальная проблема или неоптимальность. Можно исправить позже.

ИТОГ: В конце дай общий вердикт:

  • ✅ APPROVE — критических проблем нет, код готов к мержу
  • ⚠️ REQUEST CHANGES — есть P0/P1, требуют исправления
  • ❌ BLOCK — серьёзные уязвимости, нужна переработка

Количество найденных проблем по приоритетам: P0: X, P1: X, P2: X

КОД ДЛЯ РЕВЬЮ: [вставьте код сюда]

КОНТЕКСТ (опционально):

  • Язык/фреймворк: [например, Python/FastAPI]
  • Что делает этот код: [краткое описание]
  • Какие изменения внесены: [что именно изменилось, если это diff]




💡 Совет: добавляйте контекст
Секция «КОНТЕКСТ» — необязательная, но она кардинально улучшает качество ревью. Когда модель знает, что код — это обработчик платёжного webhook, она обращает особое внимание на идемпотентность и валидацию подписей. Без контекста — просто проверяет синтаксис.
## Пример результата Допустим, на вход подан следующий Python-код: ```python from flask import Flask, request import sqlite3 import os app = Flask(__name__) @app.route("/user") def get_user(): user_id = request.args.get("id") conn = sqlite3.connect("app.db") cursor = conn.cursor() cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") user = cursor.fetchone() return {"name": user[1], "email": user[2]} @app.route("/upload", methods=["POST"]) def upload(): file = request.files["file"] path = os.path.join("/uploads", file.filename) file.save(path) return {"status": "ok"} @app.route("/config") def config(): db_password = os.environ.get("DB_PASSWORD", "admin123") return {"db_host": "prod-db.internal", "pool_size": 10}

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


P0 Безопасность: SQL-инъекция в get_user

Строка: cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") Проблема: Значение user_id подставляется в SQL-запрос напрямую через f-string. Атакующий может передать id=1 OR 1=1 и получить все записи, либо id=1; DROP TABLE users для уничтожения данных. Исправление:

cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))

P0 Безопасность: Path traversal в upload

Строка: path = os.path.join("/uploads", file.filename) Проблема: file.filename может содержать ../../etc/passwd или другие пути. Атакующий перезаписывает произвольные файлы на сервере. Исправление:

from werkzeug.utils import secure_filename
safe_name = secure_filename(file.filename)
path = os.path.join("/uploads", safe_name)

P1 Безопасность: Захардкоженный пароль-фолбэк

Строка: db_password = os.environ.get("DB_PASSWORD", "admin123") Проблема: Если переменная окружения не задана, используется пароль admin123. В продакшене это создаёт риск несанкционированного доступа. Исправление:

db_password = os.environ["DB_PASSWORD"]  # упадёт явно, если не задан

P1 Баги и логика: Необработанный None в get_user

Строка: return {"name": user[1], "email": user[2]} Проблема: Если пользователь не найден, user будет None, и обращение по индексу вызовет TypeError. Клиент получит 500-ошибку без объяснения. Исправление:

user = cursor.fetchone()
if user is None:
    return {"error": "User not found"}, 404
return {"name": user[1], "email": user[2]}

P1 Обработка ошибок: Незакрытое соединение с базой

Строка: conn = sqlite3.connect("app.db") Проблема: Соединение не закрывается ни явно, ни через context manager. При исключении ресурс утечёт. Исправление:

with sqlite3.connect("app.db") as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
    user = cursor.fetchone()

P2 Безопасность: Эндпоинт /config раскрывает инфраструктуру

Строка: return {"db_host": "prod-db.internal", "pool_size": 10} Проблема: Внутреннее имя хоста базы данных доступно без аутентификации. Упрощает разведку при атаке. Исправление: Удалить эндпоинт или добавить аутентификацию.


Вердикт: ❌ BLOCK — 2× P0 (SQL-инъекция, path traversal), нужна переработка

P0: 2, P1: 3, P2: 1

Сравнение приоритетов

ПриоритетЧто означаетПримерДействие
P0 — блокерУязвимость или потеря данныхSQL-инъекция, утечка секретовНе мержить, исправить немедленно
P1 — важноБаг при реальном использованииNullPointerException, утечка ресурсовИсправить до мержа
P2 — улучшениеПотенциальная проблемаНеоптимальный запрос, лишний кодМожно взять в техдолг

Вариации и настройки

Ревью с фокусом только на безопасности

Добавьте в начало промпта:

ФОКУС: Только безопасность. Игнорируй производительность, качество кода и стиль.
Проверяй по OWASP Top 10 2025:
- A01: Broken Access Control
- A02: Cryptographic Failures
- A03: Injection
- A07: Security Misconfiguration

Ревью инфраструктурного кода

КОНТЕКСТ: Это Terraform/Docker/CI-конфигурация.
Дополнительно проверяй:
- Привилегированные контейнеры и избыточные capabilities
- Секреты в переменных окружения вместо vault/secrets manager
- Отсутствие ограничений ресурсов (CPU/memory limits)
- Публичные security groups / открытые порты

Ревью с учётом стандартов команды

СТАНДАРТЫ КОМАНДЫ:
- Все SQL-запросы через ORM (SQLAlchemy), raw SQL запрещён
- Обязательный type hints для публичных функций
- Логирование через structlog, не через print/logging
- Максимальная длина функции: 30 строк
⚠ Ограничения
LLM-ревью не заменяет: (1) интеграционное тестирование — модель не запускает код; (2) архитектурные решения — модель не знает ваш бизнес-контекст целиком; (3) линтеры и SAST-инструменты (Semgrep, Bandit) — для полного покрытия комбинируйте подходы.

Автоматизация: промпт в CI/CD

Для интеграции в pipeline используйте промпт как системный message через API:

import anthropic

client = anthropic.Anthropic()

def review_code(code: str, language: str, description: str = "") -> str:
    system_prompt = """Ты — senior software engineer..."""  # полный промпт выше

    user_message = f"""КОД ДЛЯ РЕВЬЮ:
```{language}
{code}

КОНТЕКСТ:

  • Язык/фреймворк: {language}

  • Что делает этот код: {description}"""

    message = client.messages.create( model=“claude-sonnet-4-6-20260410”, max_tokens=4096, system=system_prompt, messages=[{“role”: “user”, “content”: user_message}] ) return message.content[0].text





📝 Пример интеграции с GitHub Actions
Популярный подход — запускать LLM-ревью автоматически на каждый pull request. Инструменты вроде CodeRabbit и ai-code-review делают это из коробки. Для собственного решения: GitHub Action получает diff, отправляет в API, результат постит как комментарий к PR.
## Советы по улучшению **1. Подавайте diff, а не весь файл.** Если ревьюите изменения, а не весь файл — отправляйте `git diff`. Модель сфокусируется на том, что изменилось, и не будет отвлекаться на старый код. **2. Указывайте фреймворк.** «Python» и «Python/Django» — два разных ревью. Зная фреймворк, модель проверит специфичные паттерны: N+1 в Django ORM, небезопасные сериализаторы в DRF, CSRF-токены в формах. **3. Добавляйте примеры ваших стандартов.** Если в команде есть style guide или ADR — вставьте ключевые правила в секцию «СТАНДАРТЫ». Модель будет проверять код не только по общим практикам, но и по вашим конвенциям. **4. Итерируйте.** После первого ревью отправьте исправленный код на повторную проверку с пометкой: «Проверь, что все P0 и P1 из предыдущего ревью исправлены». > Промпт для ревью — не замена процессу, а усилитель. Он ловит 80% механических проблем за секунды, освобождая человеку время для обсуждения архитектуры и бизнес-логики.

graph TD
    A["Разработчик пишет код"] --> B["Самопроверка: LLM-ревью"]
    B --> C{"P0 найдены?"}
    C -->|Да| D["Исправить и повторить"]
    D --> B
    C -->|Нет| E["Создать Pull Request"]
    E --> F["CI: автоматическое LLM-ревью"]
    F --> G["Человек-ревьюер"]
    G --> H{"Approve?"}
    H -->|Да| I["Мерж в main"]
    H -->|Нет| D