Структурный поиск шаблонов

Разработчик или инженер по безопасности ищет код, соответствующий структурным шаблонам с CPG-ограничениями, на основе AST-движка GoCPG.

Содержание

Быстрый старт

/select pattern_search

Или через CLI:

# Ad-hoc поиск шаблона
python -m src.cli patterns search "malloc($x)" --lang c

# Сканирование по всем правилам
python -m src.cli patterns scan

# Сканирование по конкретному правилу
python -m src.cli patterns scan --rule unchecked-return

Как это работает

Архитектура

Структурный поиск шаблонов — это автономный инструмент (не LangGraph-сценарий), доступный через CLI, REST API и MCP. Бэкенд — движок паттернов GoCPG, взаимодействие по gRPC:

CLI / REST API / MCP
        |
        v
  GoCPGClient (.scan(), .search(), .validate_rule())
        |  gRPC
        v
  gocpg binary (AST-сопоставление + CPG-ограничения)
        |
        v
  DuckDB (cpg_pattern_results, cpg_pattern_rules)
        |
        v
  PatternQueriesMixin (Python читает сохранённые результаты)
        |
        +---> PatternTaintBridge (обогащение taint-путями)
        +---> SSRAutofixBridge (генерация исправлений безопасности)

GoCPGClient.scan() запускает YAML-правила против базы CPG. GoCPGClient.search() выполняет ad-hoc AST-сопоставление. Результаты сохраняются в cpg_pattern_results и читаются через PatternQueriesMixin в src/services/cpg/pattern_queries.py.

Типы шаблонов

Синтаксические шаблоны — CST-шаблоны tree-sitter с метапеременными:

Метапеременная Что соответствует
$VAR Любое выражение или идентификатор
$$ARGS Ноль или более аргументов
$_ Любой узел (подстановка)
# Найти вызовы malloc
python -m src.cli patterns search "malloc($x)" --lang c

# Найти if-return без else
python -m src.cli patterns search "if ($cond) { return $val; }" --lang c

Шаблоны с CPG-ограничениями — шаблоны с ограничениями на поток данных, граф вызовов, типы и домен:

id: unchecked-return
pattern: "$ret = $func($$args)"
language: c
constraints:
  - type: data_flow
    from: "$ret"
    not_reaches: "if ($ret"
  - type: call_graph
    callee: "$func"
    returns: "int"
message: "Возвращаемое значение $func не проверяется"
severity: warning

YAML-правила

Предопределённые правила в configs/rules/ — 190 правил для 14 языков. Доменные правила автоматически загружаются из активного доменного плагина с --domain-rules.

Использование CLI

6 подкоманд под python -m src.cli patterns:

# Сканирование по всем правилам
python -m src.cli patterns scan --db data/projects/test.duckdb

# Сканирование с фильтром серьёзности и выводом в SARIF
python -m src.cli patterns scan --severity error --format sarif --output results.sarif

# Сканирование с автозагрузкой доменных правил
python -m src.cli patterns scan --domain-rules

# Инкрементальное сканирование
python -m src.cli patterns scan --incremental

# Сканирование конкретного правила
python -m src.cli patterns scan --rule unchecked-return

# Ad-hoc поиск шаблона
python -m src.cli patterns search "malloc($SIZE)" --lang c --max-results 50

# Применение исправлений (предпросмотр)
python -m src.cli patterns fix --dry-run

# Применение исправлений (с подтверждением)
python -m src.cli patterns fix --rule unchecked-return

# Список загруженных правил
python -m src.cli patterns list

# Статистика шаблонов
python -m src.cli patterns stats

# Генерация правила из описания на естественном языке
python -m src.cli patterns generate "найти непроверенные возвращаемые значения" --lang c --output rule.yaml

Форматы вывода: text (по умолчанию), json, sarif. Подкоманда fix использует ApprovalEngine для интерактивного подтверждения перед применением изменений.

REST API

6 эндпоинтов, смонтированных на /api/v1/patterns/:

Метод Эндпоинт Описание
POST /api/v1/patterns/search Ad-hoc структурный поиск шаблонов
GET /api/v1/patterns/findings Запрос сохранённых результатов (фильтры: rule_id, severity, filename, category)
GET /api/v1/patterns/stats Агрегированная статистика по серьёзности, категории, правилу
GET /api/v1/patterns/rules Список загруженных правил из cpg_pattern_rules
POST /api/v1/patterns/generate Генерация YAML-правила через LLM
POST /api/v1/patterns/fix Применение SSR-исправлений (dry_run=true по умолчанию, требуется подтверждение)

Пример:

# Поиск шаблонов
curl -X POST http://localhost:8000/api/v1/patterns/search \
  -H "Content-Type: application/json" \
  -d '{"pattern": "malloc($x)", "language": "c", "max_results": 50}'

# Получить результаты по правилу
curl "http://localhost:8000/api/v1/patterns/findings?rule_id=unchecked-return"

# Статистика
curl http://localhost:8000/api/v1/patterns/stats

# Список правил
curl http://localhost:8000/api/v1/patterns/rules

# Генерация правила
curl -X POST http://localhost:8000/api/v1/patterns/generate \
  -H "Content-Type: application/json" \
  -d '{"description": "найти непроверенные возвращаемые значения", "language": "c"}'

# Применение исправления (предпросмотр)
curl -X POST http://localhost:8000/api/v1/patterns/fix \
  -H "Content-Type: application/json" \
  -d '{"rule_id": "unchecked-return", "dry_run": true}'

MCP-инструменты

6 инструментов, зарегистрированных в src/mcp/tools/patterns.py:

Инструмент Параметры Описание
codegraph_pattern_search pattern, language, max_results AST-поиск структурных шаблонов
codegraph_pattern_findings rule_id?, severity?, filename?, category?, limit Запрос сохранённых результатов
codegraph_pattern_stats (нет) Агрегированная статистика
codegraph_pattern_fix rule_id?, dry_run Применение SSR-исправлений
codegraph_pattern_generate description, language, with_fix Генерация YAML-правила через LLM
codegraph_pattern_test rule_yaml, code_snippet, language Тестирование правила на фрагменте кода

Модели данных

Ключевые модели из src/services/gocpg/models.py:

Модель Ключевые поля
ScanConfig rule_dirs, rule_id, severity_filter, incremental, fix, dry_run, output_format, output_path, domain_rules
GoCPGScanResult findings, rules_evaluated, files_scanned, total_matches, duration_ms, incremental, sarif_path
GoCPGSearchResult matches, pattern, language, files_searched
GeneratedRule yaml_text, rule_id, language, has_fix, validated, validation_errors, generation_attempts

Генерация правил через LLM

LLMPatternGenerator в src/analysis/patterns/llm_pattern_generator.py генерирует YAML-правила из описаний на естественном языке:

  1. Строит структурированный промпт из config/prompts/patterns/generate_pattern.yaml
  2. Вызывает настроенного LLM-провайдера
  3. Парсит YAML из ответа
  4. Валидирует через gocpg validate-rule (до 3 попыток при ошибках)
  5. Возвращает GeneratedRule со статусом валидации
# CLI
python -m src.cli patterns generate "найти SQL-запросы, собранные конкатенацией строк" --lang python --output rule.yaml

# MCP
codegraph_pattern_generate(description="найти непроверенные вызовы malloc", language="c", with_fix=true)

Метод generate_rule() является асинхронным. Параметр with_fix управляет включением шаблона fix: в генерируемое правило.

Интеграция с безопасностью

PatternTaintBridge

PatternTaintBridge в src/analysis/patterns/taint_bridge.py обогащает результаты структурного поиска данными taint-анализа из S02 (аудит безопасности):

  • Конструктор: PatternTaintBridge(cpg_service, taint_propagator=None)
  • Метод: enrich_findings_with_taint(findings) (async)
  • Для результатов с has_cpg=True запрашивает CPG на предмет taint-путей, проходящих через найденный узел
  • Добавляет ключи taint_paths и taint_enriched к каждому результату

Это связывает структурное обнаружение паттернов с анализом уязвимостей — результат паттерна в конкретном месте кода можно сопоставить с данными taint-потока, чтобы определить, достигают ли недоверенные данные этого места.

SSR Autofix Bridge

SSRAutofixBridge в src/analysis/autofix/ssr_bridge.py связывает SSR-правила движка паттернов с AutofixEngine, описанным в Аудит безопасности: автоисправление:

  • Маппит типы уязвимостей на идентификаторы SSR-правил в configs/rules/autofix/
  • Запускает gocpg scan --fix --dry-run пакетно по файлам для получения AST-превью исправлений
  • Преобразует результаты в объекты FixSuggestion для конвейера автоисправления

Маппинг типов уязвимостей (выдержка):

Уязвимость SSR-правила
sql_injection autofix-sprintf-snprintf, autofix-py-format-sql, autofix-go-sprintf-sql, …
buffer_overflow autofix-sprintf-snprintf, autofix-strcpy, autofix-py-ctypes, autofix-go-cgo-strcpy
null_dereference autofix-null-assert
command_injection autofix-py-subprocess, autofix-go-exec

Цепочка: Сканирование паттернов обнаруживает проблемы → SSRAutofixBridge маппит на правила исправления → AutofixEngine генерирует патчи → DiffValidator проверяет. SSR-исправления имеют наивысшую уверенность (0.8-1.0) в конвейере автоисправления. См. Аудит безопасности: автоисправление для полной архитектуры.

Таблицы БД

GoCPG сохраняет результаты сканирования в DuckDB:

  • cpg_pattern_results — результаты: id, rule_id, severity, category, filename, line_number, column_number, code, message, confidence, match_data, cpg_context
  • cpg_pattern_rules — загруженные правила: rule_id, language, severity, category, has_cpg, rule_source

Python читает их через методы PatternQueriesMixin: get_pattern_findings(), get_pattern_rules(), get_pattern_statistics().

Примеры запросов

Найти непроверенные возвращаемые значения
Найти malloc без free
Показать функции с антишаблонами обработки ошибок
Найти конструирование SQL-запросов без параметризации
Найти все функции с цикломатической сложностью > 20

Связанное