Руководство пользователя CodeGraph¶
Комплексная документация по анализу кода с использованием графов свойств кода (CPG)
Содержание¶
- Быстрый старт
- Сценарии для разработчиков
- Сценарии для специалистов по информационной безопасности - Укрепление исходного кода по D3FEND
- Сценарии для технических писателей
- Справочник команд TUI
- Руководство по настройке
- Приложение: все 21 сценарий
- Отчёты по аудиту безопасности (CLI)
- Типовые рабочие процессы
- Темы оформления
- Сессии
- Советы и хитрости
- Устранение неполадок
Быстрый старт¶
Установка¶
# Клонируйте репозиторий и установите зависимости
cd codegraph
pip install -r requirements.txt
# Настройте учетные данные API (выберите один вариант)
export GIGACHAT_AUTH_KEY="ваш-ключ-здесь" # GigaChat (Сбер)
# ИЛИ
export OPENAI_API_KEY="ваш-ключ-здесь" # OpenAI
Запуск TUI¶
python -m src.tui.app
Ваш первый запрос¶
╭─────────────────────────────────────────────────────────╮
│ Интерактивная консоль CodeGraph │
│ Введите /help для получения списка команд, /exit для выхода │
╰─────────────────────────────────────────────────────────╯
> Где определена функция heap_insert?
╭─────────────── Ответ ────────────────╮
│ heap_insert определена в: │
│ src/backend/access/heap/heapam.c │
│ Строка: 2156 │
│ │
│ Сигнатура: │
│ void heap_insert(Relation relation, │
│ HeapTuple tup, │
│ CommandId cid, │
│ ...) │
╰───────────────────────────────────────╯
Основные команды¶
| Команда | Описание |
|---|---|
| /help | Показать все доступные команды |
| /scenarios | Вывести список из 21 сценария анализа |
| /select 02 | Переключиться в режим аудита безопасности |
| /project | Переключение между проектами CPG |
| /review git | Просмотреть текущие изменения в коде |
| /stat | Показать статистику базы данных |
| /generate-docs | Сгенерировать полную документацию проекта |
| /exit | Сохранить сессию и выйти |
Сценарии для разработчиков¶
День 1: Освоение кодовой базы¶
Сценарий: Новый разработчик присоединяется к команде и должен быстро понять структуру кодовой базы.
Шаг 1: Выберите сценарий освоения¶
/select 01
Шаг 2: Задайте обзорные вопросы¶
> Что такое подсистема исполнителя (executor)?
╭─────────────── Ответ ────────────────╮
│ Подсистема исполнителя отвечает за │
│ выполнение планов запросов, │
│ сгенерированных планировщиком. │
│ │
│ Основные компоненты: │
│ - ExecutorStart: Инициализация │
│ - ExecutorRun: Основной цикл │
│ - ExecutorEnd: Освобождение ресурсов│
│ │
│ Точка входа: src/backend/executor/ │
│ execMain.c │
╰──────────────────────────────────────╯
> Каковы основные точки входа в исполнитель?
> Покажите архитектуру выполнения запросов
Шаг 3: Погрузитесь в детали¶
> Что делает ExecProcNode?
> Кто вызывает ExecutorRun?
> Объясните связь между Plan и PlanState
Пример из реальной практики: Понимание управления памятью¶
> Как работает выделение памяти в PostgreSQL?
╭─────────────── Ответ ────────────────╮
│ PostgreSQL использует контексты │
│ памяти для иерархического управления│
│ памятью: │
│ │
│ Основные функции: │
│ palloc() - Выделить память │
│ pfree() - Освободить память │
│ MemoryContextCreate() - Новый контекст│
│ MemoryContextReset() - Массовое освобождение│
│ │
│ Основные контексты: │
│ TopMemoryContext - Корневой контекст│
│ CurrentMemoryContext - Текущий │
│ MessageContext - На сообщение │
╰──────────────────────────────────────╯
Поиск определений функций¶
Сценарий: Разработчику нужно найти реализации функций.
Быстрый поиск определения¶
> Где определена функция palloc?
╭─────────────── Ответ ────────────────╮
│ palloc определена в: │
│ src/backend/utils/mmgr/mcxt.c:1089 │
│ │
│ Сигнатура: │
│ void *palloc(Size size) │
│ │
│ Связанные функции: │
│ palloc0(), palloc_extended(), │
│ repalloc(), pfree() │
╰──────────────────────────────────────╯
С графом вызовов¶
> Покажите всех вызывающих palloc
╭─────────────── Вызывающие ───────────╮
│ 1. heap_form_tuple() │
│ 2. ExecStoreTuple() │
│ 3. construct_array() │
│ 4. pnstrdup() │
│ 5. SPI_connect() │
│ ... (показано первые 5 из 2 847) │
╰──────────────────────────────────────╯
> Какие функции вызывает LWLockAcquire?
Отслеживание потока данных¶
> Как проходят данные от pg_parse_query до исполнителя?
╭─────────────── Поток данных ─────────╮
│ pg_parse_query() │
│ ↓ │
│ pg_analyze_and_rewrite() │
│ ↓ │
│ pg_plan_queries() │
│ ↓ │
│ PortalRun() │
│ ↓ │
│ ExecutorRun() │
│ ↓ │
│ ExecProcNode() │
╰──────────────────────────────────────╯
Добавление новых функций¶
Сценарий: Разработчику нужно добавить новый алгоритм соединения (join).
Шаг 1: Выберите сценарий разработки функций¶
/select 04
Шаг 2: Найдите точки интеграции¶
> Где мне добавить новый алгоритм соединения?
╭─────────────── Ответ ────────────────╮
│ Чтобы добавить новый алгоритм: │
│ │
│ 1. Определите тип узла: │
│ src/include/nodes/plannodes.h │
│ │
│ 2. Добавьте поддержку в планировщик:│
│ src/backend/optimizer/path/ │
│ joinpath.c - add_xxx_path() │
│ │
│ 3. Добавьте поддержку в исполнитель:│
│ src/backend/executor/ │
│ nodeXxxjoin.c - ExecXxxJoin() │
│ │
│ 4. Зарегистрируйте в execProcnode.c │
╰──────────────────────────────────────╯
> Какие хуки существуют в исполнителе для пользовательских узлов плана?
> Покажите, как hashjoin интегрируется с планировщиком
Шаг 3: Оцените влияние изменений¶
> Что сломается, если я изменю add_path?
╭──────────── Анализ влияния ──────────╮
│ Изменение add_path() повлияет на: │
│ │
│ Прямые вызывающие (47): │
│ - add_partial_path() │
│ - add_partial_path_precheck() │
│ - create_seqscan_path() │
│ - create_index_path() │
│ ... │
│ │
│ Риск: ВЫСОКИЙ — ядро выбора путей │
│ Рекомендация: Добавьте новую функцию │
│ вместо изменения существующей │
╰──────────────────────────────────────╯
> Покажите зависимости create_hashjoin_path
Помощь при отладке¶
Сценарий: Разработчик отлаживает сбой или неожиданное поведение.
Шаг 1: Выберите сценарий отладки¶
/select 15
Шаг 2: Найдите точки отладки¶
> Где в исполнителе используются макросы утверждений (assert)?
╭─────────────── Ответ ────────────────╮
│ Макросы утверждений в исполнителе: │
│ │
│ Assert() - src/include/c.h:846 │
│ AssertArg() - Проверка аргументов │
│ AssertState() - Проверка состояния │
│ │
│ Использование в исполнителе: │
│ execMain.c: 89 утверждений │
│ execProcnode.c: 34 утверждения │
│ execScan.c: 23 утверждения │
╰──────────────────────────────────────╯
> Найдите вызовы elog в heap_insert
> Какие функции пишут в WAL?
Шаг 3: Отследите выполнение¶
> Отследите выполнение от INSERT до heap_insert
╭──────────── Трассировка выполнения ──╮
│ ProcessQuery() │
│ ↓ │
│ PortalRunMulti() │
│ ↓ │
│ ExecutorRun() │
│ ↓ │
│ ExecModifyTable() │
│ ↓ │
│ ExecInsert() │
│ ↓ │
│ table_tuple_insert() │
│ ↓ │
│ heap_insert() │
╰──────────────────────────────────────╯
> Где поставить точки останова для фиксации транзакции?
Рефакторинг кода¶
Сценарий: Разработчик устраняет технический долг во время спринта рефакторинга.
Шаг 1: Выберите сценарий рефакторинга¶
/select 05
Шаг 2: Найдите неиспользуемый код¶
> Найдите неиспользуемые статические функции в исполнителе
╭──────────── Неиспользуемый код ──────╮
│ Потенциально неиспользуемые функции: │
│ │
│ 1. execUtils.c: │
│ - old_get_typlenbyval() :234 │
│ │
│ 2. execTuples.c: │
│ - legacy_slot_init() :456 │
│ │
│ Всего: 12 кандидатов │
│ Подтверждено неиспользуемых: 8 │
╰──────────────────────────────────────╯
> Покажите устаревшие функции, которые всё ещё используются
> Найдите дублирующиеся шаблоны обработки ошибок
Шаг 3: Планирование рефакторинга¶
> От чего зависит ExecProcNode?
╭──────────── Зависимости ─────────────╮
│ Прямые зависимости: 47 │
│ Транзитивные зависимости: 312 │
│ │
│ Ключевые вызывающие: │
│ - ExecutorRun() │
│ - ExecSubPlan() │
│ - ExecMaterial() │
│ - ExecSort() │
│ │
│ Риск рефакторинга: КРИТИЧЕСКИЙ │
│ Рекомендация: Поэтапная миграция │
╰──────────────────────────────────────╯
> Влияние переименования heap_open в table_open
Сценарии для QA/тестировщиков¶
Анализ покрытия тестами¶
Сценарий: Инженеру по тестированию необходимо выявить непротестированные участки кода.
Шаг 1: Выбор сценария анализа покрытия тестами¶
/select 07
Шаг 2: Поиск пробелов в покрытии¶
> Какие функции не покрыты тестами?
╭─────────────── Пробелы в покрытии ─────────╮
│ Функции без прямых тестов: │
│ │
│ Критические (executor): │
│ - ExecParallelHashJoinNewBatch() │
│ - ExecReScanGather() │
│ │
│ Высокий приоритет (storage): │
│ - heap_lock_updated_tuple() │
│ - heap_abort_speculative() │
│ │
│ Всего непротестированных: 234 функции │
│ Оценка покрытия: 78% │
╰───────────────────────────────────────────╯
> Какие критические функции нужно протестировать в первую очередь?
> Найти непротестированные пути обработки ошибок
Шаг 3: Определение приоритетов тестирования¶
> Какие непротестированные функции имеют наибольшее влияние?
╭─────────────── Список приоритетов ─────────╮
│ Высокое влияние + нет тестов: │
│ │
│ 1. heap_lock_updated_tuple() │
│ Влияние: Целостность транзакций │
│ Количество вызовов: 23 │
│ │
│ 2. ExecParallelHashJoinNewBatch() │
│ Влияние: Корректность параллельных запросов │
│ Количество вызовов: 8 │
│ │
│ 3. AtEOXact_RelationCache() │
│ Влияние: Согласованность кеша │
│ Количество вызовов: 4 │
╰────────────────────────────────────────────╯
> Показать точки входа без тестов
Помощь при проверке кода¶
Сценарий: Рецензенту необходимо проанализировать запрос на слияние на наличие проблем с качеством и безопасностью.
Вариант A: GitHub PR¶
/review github 123
Вариант B: GitLab MR¶
/review gitlab 456
Вариант C: Локальные изменения в Git¶
/review git
Вариант D: Файл изменений¶
/review file path/to/changes.patch
Понимание результата¶
╭─────────────── Результаты ревью ────────────────────────────╮
│ │
│ Оценка: 72/100 Рекомендация: REQUEST_CHANGES │
│ │
│ ══════════════════════════════════════════════════════ │
│ │
│ Найденные проблемы: │
│ │
│ 🔴 КРИТИЧЕСКИЙ Риск SQL-инъекции │
│ Местоположение: src/api/user_query.c:45 │
│ Паттерн: Ввод пользователя вставляется в запрос напрямую │
│ Исправление: Использовать параметризованные запросы │
│ │
│ 🟡 СРЕДНИЙ Сложность по Маккейбу │
│ Местоположение: src/parser/gram.y:1234 │
│ Значение: 47 (порог: 10) │
│ Исправление: Вынести вспомогательные функции │
│ │
│ 🟢 НИЗКИЙ Отсутствует проверка на NULL │
│ Местоположение: src/utils/string.c:89 │
│ Исправление: Добавить проверку указателя на NULL │
│ │
╰─────────────────────────────────────────────────────────────╯
Проверка кода с встроенными комментариями¶
/review git --format md --inline
╭─────────────── Встроенные комментарии ───────────────────────────╮
│ │
│ src/api/user_query.c │
│ ───────────────────── │
│ │
│ Строка 45: │
│ sprintf(query, "SELECT * FROM users WHERE id=%s", id); │
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^│
│ 🔴 SQL-инъекция: Используйте snprintf с правильным экранированием │
│ │
│ Строка 67: │
│ char *result = malloc(len); │
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ │
│ 🟡 Память: Проверьте возвращаемое значение malloc на NULL │
│ │
╰───────────────────────────────────────────────────────────────────╯
Генерация тестовых сценариев¶
Сценарий: QA-инженеру необходимо создать комплексные тесты для функции.
> Сгенерируй тестовые сценарии для heap_insert
╭─────────────── Тестовые сценарии ────────────────────────────────╮
│ │
│ Функция: heap_insert() │
│ Файл: src/backend/access/heap/heapam.c:2156 │
│ │
│ ═════════════════════════════════════════════════════════ │
│ │
│ 1. Обычная вставка │
│ Входные данные: Корректная таблица, корректный кортеж, │
│ корректный CommandId │
│ Ожидаемое: Возвращён OID, кортеж виден │
│ │
│ 2. NULL в указателе таблицы │
│ Входные данные: Указатель таблицы равен NULL │
│ Ожидаемое: Сбой утверждения или корректное сообщение об ошибке │
│ │
│ 3. Слишком большой кортеж │
│ Входные данные: Кортеж больше BLCKSZ │
│ Ожидаемое: Ошибка с понятным сообщением │
│ │
│ 4. Параллельная вставка │
│ Входные данные: Несколько потоков выполняют вставку │
│ Ожидаемое: Все вставки успешны, без повреждений данных │
│ │
│ 5. Откат транзакции │
│ Входные данные: Вставка, за которой следует ROLLBACK │
│ Ожидаемое: Кортеж не виден после отката │
│ │
│ 6. Требуется TOAST │
│ Входные данные: Кортеж с большим полем varlena │
│ Ожидаемое: TOAST-таблица заполнена корректно │
│ │
╰──────────────────────────────────────────────────────────────────╯
> Какие граничные случаи нужно протестировать в LWLockAcquire?
> Создай тестовые данные для сценариев фиксации транзакций
Сценарии специалиста по информационной безопасности¶
Сканирование уязвимостей¶
Сценарий: Инженер по безопасности проводит аудит в рамках спринта.
Шаг 1: Выбор сценария безопасности¶
/select 02
Шаг 2: Поиск уязвимостей¶
> Найти уязвимости типа SQL-инъекция
╭─────────────── Результаты проверки безопасности ─────────────────────────╮
│ │
│ 🔴 КРИТИЧЕСКИЙ: SQL-инъекция │
│ ────────────────────────────────────── │
│ │
│ Расположение: src/pl/plpgsql/src/pl_exec.c:4567 │
│ Паттерн: Динамический запрос с конкатенацией строк │
│ Код: │
│ snprintf(query, "SELECT * FROM %s", table_name); │
│ │
│ Риск: Управляемое пользователем имя таблицы может внедрить SQL │
│ Исправление: Использовать quote_identifier() для имён таблиц │
│ CWE: CWE-89 │
│ │
│ ──────────────────────────────────────────────────────────────────────── │
│ │
│ Расположение: src/backend/utils/adt/ruleutils.c:2341 │
│ Паттерн: Строка формата с внешним вводом │
│ Риск: Потенциальная инъекция строки формата │
│ Исправление: Проверить спецификаторы формата │
│ │
│ Всего найдено: 7 критических, 12 высоких, 34 средних │
│ │
╰───────────────────────────────────────────────────────────────────────────╯
> Найти риски переполнения буфера в строковых функциях
> Показать функции, использующие sprintf без проверки границ
Анализ потока заражённых данных (Taint Flow Analysis)¶
Сценарий: Инженер по безопасности отслеживает ненадёжные данные через систему.
Шаг 1: Определение точек входа¶
> Найти все внешние точки входа
╭─────────────── Точки входа ──────────────────────────────╮
│ │
│ Сетевые точки входа: │
│ - pq_getmsgstring() - Чтение строки от клиента │
│ - pq_getmsgint() - Чтение целого от клиента │
│ - ProcessClientRead() - Прямое чтение из сокета │
│ │
│ Точки входа SQL: │
│ - exec_simple_query() - Прямое выполнение SQL │
│ - exec_parse_message() - Подготовленный оператор │
│ - exec_bind_message() - Привязка параметров │
│ │
│ Файловые точки входа: │
│ - pg_read_file() - Чтение произвольного файла │
│ - pg_ls_dir() - Просмотр содержимого папки │
│ │
│ Всего: обнаружено 47 точек входа │
│ │
╰───────────────────────────────────────────────────────────╯
> Показать обработчики сетевого ввода
> Перечислить функции ввода пользователя
Шаг 2: Отслеживание потока данных¶
> Отследить поток данных от PQgetvalue до выполнения SQL
╭─────────────── Поток заражённых данных ────────────────────────╮
│ │
│ ИСТОЧНИК: PQgetvalue() [Ввод клиента] │
│ ↓ │
│ pq_getmsgstring() │
│ ↓ │
│ exec_simple_query() │
│ ↓ │
│ pg_parse_query() │
│ ↓ │
│ СТОК: SPI_execute() [Выполнение SQL] │
│ │
│ ════════════════════════════════════════════════════ │
│ │
│ Санация найдена: ДА │
│ Расположение: pg_parse_query() проверяет синтаксис │
│ НО: Не предотвращает семантическую инъекцию │
│ │
│ Уровень риска: ВЫСОКИЙ │
│ Рекомендация: Добавить проверку ввода на точке входа │
│ │
╰───────────────────────────────────────────────────────────────╯
> Достигает ли ввод пользователя strcpy без проверки?
> Показать путь от чтения из сокета до выделения памяти
Шаг 3: Поиск санации данных¶
> Где ввод санируется перед выполнением запроса?
╭─────────────── Точки санации данных ───────────────────────╮
│ │
│ Обнаруженные средства санации: │
│ │
│ 1. quote_identifier() │
│ Расположение: src/backend/utils/adt/ruleutils.c:10234 │
│ Назначение: Экранирование идентификаторов SQL │
│ Охват: Частичный — не всегда используется │
│ │
│ 2. quote_literal() │
│ Расположение: src/backend/utils/adt/quote.c:45 │
│ Назначение: Экранирование литералов SQL │
│ Охват: Хороший — широко используется │
│ │
│ 3. pg_parse_query() │
│ Расположение: src/backend/tcop/postgres.c:645 │
│ Назначение: Проверка синтаксиса │
│ Охват: Все запросы │
│ │
│ Отсутствует санация в: │
│ - Построение имён таблиц (12 мест) │
│ - Построение строк формата (5 мест) │
│ │
╰───────────────────────────────────────────────────────────╯
> Найти все функции проверки в аутентификации
Укрепление исходного кода по D3FEND¶
Сценарий: Инженер по безопасности проверяет практики оборонительного программирования с использованием фреймворка MITRE D3FEND.
Модуль D3FEND анализирует код на соответствие 11 методикам укрепления исходного кода, определённым MITRE:
| ID | Методика | Описание | CWE |
|---|---|---|---|
| D3-VI | Инициализация переменных | Неинициализированные переменные | CWE-457 |
| D3-CS | Очистка учётных данных | Жёстко заданные учётные данные | CWE-798 |
| D3-IRV | Проверка диапазона целых | Риски переполнения целых | CWE-190 |
| D3-PV | Проверка указателей | Разыменование указателя без проверки | CWE-476 |
| D3-RN | Обнуление ссылок | Риски использования после освобождения | CWE-416 |
| D3-TL | Надёжные библиотеки | Использование небезопасных функций | CWE-676 |
| D3-VTV | Проверка типа переменных | Проблемы с типами | CWE-704 |
| D3-MBSV | Проверка начала блока памяти | Выход за границы буфера | CWE-119 |
| D3-NPC | Проверка на null-указатель | Отсутствие проверок NULL | CWE-476 |
| D3-DLV | Проверка логики домена | Ошибки бизнес-логики | CWE-20 |
| D3-OLV | Проверка операционной логики | Управление состоянием | CWE-754 |
Пример 1: Полный аудит укрепления¶
/select 02
> Выполнить проверку соответствия D3FEND
╭─────────────── Отчёт о соответствии D3FEND ─────────────────────╮
│ │
│ Общий балл соответствия: 72,5% │
│ │
│ ═══════════════════════════════════════════════════════════ │
│ │
│ Найденные проблемы по методикам: │
│ │
│ D3-VI (Инициализация переменных): 23 проблемы │
│ ────────────────────────────────────────────────────── │
│ - palloc без palloc0: 15 мест │
│ - Неинициализированные поля структур: 8 мест │
│ │
│ D3-TL (Надёжные библиотеки): 12 проблем │
│ ───────────────────────────────────────────────────── │
│ 🔴 использование strcpy: src/backend/utils/adt/varlena.c:234│
│ 🔴 использование sprintf: src/backend/libpq/auth.c:567 │
│ 🟡 использование strtok: src/backend/parser/gram.c:1234 │
│ │
│ D3-NPC (Проверка на null-указатель): 8 проблем │
│ ────────────────────────────────────────────────────── │
│ - malloc без проверки на NULL: 5 мест │
│ - palloc без проверки: 3 места │
│ │
│ D3-RN (Обнуление ссылок): 6 проблем │
│ ────────────────────────────────────────────────────── │
│ - pfree без ptr = NULL: 6 мест │
│ │
│ Баллы по категориям: │
│ Инициализация: 65% │
│ Безопасность памяти: 78% │
│ Безопасность указателей: 82% │
│ Безопасность библиотек: 58% │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 2: Проверка конкретных методик D3FEND¶
> Проверить использование небезопасных функций (D3-TL Надёжные библиотеки)
╭─────────────── D3-TL: Надёжные библиотеки ───────────────────────╮
│ │
│ Найдено небезопасных функций: 47 │
│ │
│ 🔴 КРИТИЧЕСКИЙ - strcpy (риск переполнения буфера): │
│ ────────────────────────────────────────────────────── │
│ src/backend/utils/adt/varlena.c:234 │
│ src/backend/libpq/pqformat.c:567 │
│ src/pl/plpgsql/src/pl_exec.c:1234 │
│ │
│ 🔴 КРИТИЧЕСКИЙ - sprintf (риск строки формата): │
│ ────────────────────────────────────────────────────── │
│ src/backend/libpq/auth.c:567 │
│ src/backend/utils/error/elog.c:890 │
│ │
│ 🟡 ВЫСОКИЙ - gets (устарела, всегда небезопасна): │
│ ────────────────────────────────────────────────────── │
│ Не найдено ✓ │
│ │
│ 🟡 ВЫСОКИЙ - rand (слабый генератор случайных чисел): │
│ ────────────────────────────────────────────────────── │
│ src/backend/utils/misc/pg_random.c:45 │
│ │
│ Рекомендации по исправлению: │
│ ────────────────────────────── │
│ - strcpy → strncpy/strlcpy │
│ - sprintf → snprintf │
│ - gets → fgets │
│ - rand → pg_prng_* или arc4random │
│ │
╰───────────────────────────────────────────────────────────────╯
> Найти уязвимости из-за отсутствия проверки null-указателя (D3-NPC)
╭─────────────── D3-NPC: Проверка на null-указатель ────────────────╮
│ │
│ Отсутствие проверки NULL после выделения: 23 │
│ │
│ malloc без проверки: │
│ ───────────────────── │
│ src/backend/utils/mmgr/aset.c:345 │
│ char *buf = malloc(size); │
│ use(buf); // ← Нет проверки на NULL! │
│ │
│ palloc без проверки: │
│ ────────────────────────── │
│ src/backend/executor/execUtils.c:234 │
│ TupleTableSlot *slot = palloc(sizeof(...)); │
│ slot->tts_values = palloc(...); // ← Нет проверки │
│ │
│ Примечание PostgreSQL: palloc() вызывает ERROR при нехватке памяти,│
│ но явные проверки улучшают читаемость кода. │
│ │
│ Пример исправления: │
│ ───────────────────── │
│ char *buf = malloc(size); │
│ if (buf == NULL) { │
│ ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY))); │
│ } │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 3: Проверка безопасности памяти (D3-RN Обнуление ссылок)¶
> Проверить риски использования после освобождения
╭─────────────── D3-RN: Обнуление ссылок ────────────────╮
│ │
│ Освобождение без обнуления: 34 места │
│ │
│ pfree без присвоения NULL: │
│ ────────────────────────────── │
│ │
│ src/backend/utils/cache/relcache.c:567 │
│ ───────────────────────────────────── │
│ pfree(rel->rd_options); │
│ // rel->rd_options всё ещё указывает на освобождённую память! │
│ │
│ ✓ ИСПРАВЛЕНИЕ: │
│ pfree(rel->rd_options); │
│ rel->rd_options = NULL; │
│ │
│ src/backend/executor/nodeHash.c:234 │
│ ───────────────────────────────── │
│ pfree(hashtable->buckets); │
│ // Риск висячего указателя в путях обработки ошибок │
│ │
│ MemoryContextDelete без обнуления: │
│ ────────────────────────────────────────── │
│ │
│ src/backend/utils/mmgr/mcxt.c:890 │
│ MemoryContextDelete(ctx); │
│ // ctx может быть использован позже! │
│ │
│ Справка CWE: CWE-416 (Использование после освобождения) │
│ │
╰───────────────────────────────────────────────────────╯
Пример 4: Проверка инициализации переменных (D3-VI)¶
> Найти неинициализированные переменные
╭─────────────── D3-VI: Инициализация переменных ───────────────╮
│ │
│ Найдено неинициализированных переменных: 56 │
│ │
│ Локальные переменные без инициализации: │
│ ────────────────────────────────────────────────────── │
│ │
│ src/backend/executor/execMain.c:456 │
│ ───────────────────────────────────── │
│ EState *estate; // ← Неинициализирована │
│ QueryDesc *queryDesc; // ← Неинициализирована │
│ │
│ ✓ ИСПРАВЛЕНИЕ: │
│ EState *estate = NULL; │
│ QueryDesc *queryDesc = NULL; │
│ │
│ palloc без palloc0: │
│ ─────────────────── │
│ │
│ src/backend/nodes/copyfuncs.c:234 │
│ ───────────────────────────────── │
│ Node *newnode = palloc(sizeof(Node)); │
│ // Поля могут содержать мусор! │
│ │
│ ✓ ИСПРАВЛЕНИЕ: │
│ Node *newnode = palloc0(sizeof(Node)); │
│ │
│ Структура без memset: │
│ ────────────────────── │
│ │
│ struct MyStruct s; // ← Неинициализированные поля │
│ ✓ ИСПРАВЛЕНИЕ: │
│ struct MyStruct s = {0}; // Нулевая инициализация │
│ │
│ Справка CWE: CWE-457 (Использование неинициализированной переменной) │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 5: Очистка учётных данных (D3-CS)¶
> Найти жёстко заданные учётные данные
╭─────────────── D3-CS: Очистка учётных данных ──────────────────╮
│ │
│ 🔴 КРИТИЧЕСКИЙ: Обнаружены жёстко заданные учётные данные │
│ │
│ Литералы паролей: │
│ ───────────────── │
│ │
│ src/backend/libpq/auth.c:123 │
│ ───────────────────────────── │
│ char *default_password = "postgres123"; │
│ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ │
│ // НИКОГДА не задавайте пароли в исходном коде! │
│ │
│ Шаблоны API-ключей: │
│ ──────────────────── │
│ │
│ src/contrib/postgres_fdw/connection.c:456 │
│ ────────────────────────────────────────── │
│ #define AWS_SECRET_KEY "AKIAIOSFODNN7EXAMPLE" │
│ // Учётные данные в исходном коде! │
│ │
│ Шаблоны токенов: │
│ ──────────────── │
│ Не найдено ✓ │
│ │
│ Рекомендации по исправлению: │
│ ──────────────────────────── │
│ - Используйте переменные окружения: getenv("DB_PASSWORD") │
│ - Используйте защищённые хранилища учётных данных │
│ - Используйте файл .pgpass для PostgreSQL │
│ - Реализуйте ротацию учётных данных │
│ │
│ Справка CWE: CWE-798 (Использование жёстко заданных учётных данных) │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 6: Проверка диапазона целых чисел (D3-IRV)¶
> Проверить риски переполнения целых чисел
╭─────────────── D3-IRV: Проверка диапазона целых чисел ─────────╮
│ │
│ Рисков переполнения целых: 18 │
│ │
│ Вычисление размера выделения без проверки: │
│ ────────────────────────────────────────── │
│ │
│ src/backend/utils/palloc.c:234 │
│ ─────────────────────────────── │
│ size_t size = count * sizeof(int); // Может переполниться! │
│ ptr = palloc(size); │
│ │
│ ✓ ИСПРАВЛЕНИЕ (стиль PostgreSQL): │
│ if (count > SIZE_MAX / sizeof(int)) │
│ ereport(ERROR, ...); │
│ ptr = palloc(count * sizeof(int)); │
│ │
│ ✓ ИСПРАВЛЕНИЕ (с макросом проверки переполнения): │
│ if (pg_mul_s64_overflow(count, sizeof(int), &size)) │
│ ereport(ERROR, ...); │
│ ptr = palloc(size); │
│ │
│ Вычисление индекса массива: │
│ ──────────────────────────── │
│ │
│ src/backend/access/heap/heapam.c:567 │
│ ──────────────────────────────────── │
│ int offset = base + delta; // Может произойти переполнение! │
│ array[offset] = value; │
│ │
│ Справка CWE: CWE-190 (Переполнение целого числа) │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 7: Специфичные проверки для домена (PostgreSQL)¶
> Выполнить проверки укрепления, специфичные для PostgreSQL
╭─────────────── Отчёт по укреплению PostgreSQL ─────────────────╮
│ │
│ Специфичные для PostgreSQL находки D3FEND │
│ │
│ D3-VI-PG: palloc vs palloc0 │
│ ───────────────────────────── │
│ palloc без инициализации: 45 мест │
│ Рекомендация: Используйте palloc0() для структур │
│ │
│ D3-TL-PG: Стандартные C-функции vs функции PostgreSQL │
│ ───────────────────────────────────────────── │
│ использование malloc (следует использовать palloc): 12 мест │
│ использование free (следует использовать pfree): 8 мест │
│ использование strdup (следует использовать pstrdup): 5 мест │
│ │
│ D3-DLV-PG: Проверка OID │
│ ───────────────────────────── │
│ SearchSysCache без OidIsValid: 7 мест │
│ GetSysCacheOid без проверки: 3 места │
│ │
│ D3-OLV-PG: Управление состоянием SPI │
│ ─────────────────────────────── │
│ SPI_execute без SPI_connect: 2 места │
│ Отсутствует SPI_finish в путях обработки ошибок: 4 места │
│ │
│ Лучшие практики PostgreSQL: │
│ ────────────────────────── │
│ ✓ Используйте palloc/pfree вместо malloc/free │
│ ✓ Используйте palloc0 для инициализации структур │
│ ✓ Всегда проверяйте OidIsValid() перед поиском в кеше │
│ ✓ Используйте HeapTupleIsValid() после SearchSysCache │
│ ✓ Обеспечьте баланс SPI_connect/SPI_finish во всех путях │
│ │
╰───────────────────────────────────────────────────────────────╯
Пример 8: Генерация отчёта о соответствии¶
> Сгенерировать отчёт о соответствии D3FEND для аудита
╭─────────────── Отчёт аудита соответствия D3FEND ───────────────╮
│ │
│ Соответствие MITRE D3FEND по укреплению исходного кода │
│ ═══════════════════════════════════════════ │
│ │
│ Дата аудита: 2024-12-09 │
│ Объект: PostgreSQL 16.1 (src/backend/*) │
│ Язык: C │
│ │
│ КРАТКОЕ РЕЗЮМЕ │
│ ───────────────── │
│ Общий балл соответствия: 72,5% │
│ Всего находок: 156 │
│ - Критических: 12 │
│ - Высоких: 34 │
│ - Средних: 67 │
│ - Низких: 43 │
│ │
│ СООТВЕТСТВИЕ ПО МЕТОДИКАМ │
│ ───────────────────── │
│ │
│ D3-VI Инициализация переменных ████████░░ 78% │
│ D3-CS Очистка учётных данных ██████████ 95% │
│ D3-IRV Проверка диапазона целых ███████░░░ 68% │
│ D3-PV Проверка указателей ████████░░ 82% │
│ D3-RN Обнуление ссылок ██████░░░░ 62% │
│ D3-TL Надёжные библиотеки █████░░░░░ 58% │
│ D3-VTV Проверка типа переменных ████████░░ 85% │
│ D3-MBSV Проверка блока памяти ███████░░░ 72% │
│ D3-NPC Проверка null-указателя ████████░░ 80% │
│ D3-DLV Проверка логики домена ███████░░░ 75% │
│ D3-OLV Проверка операц. логики ██████░░░░ 65% │
│ │
│ ПРИОРИТЕТНЫЕ ИСПРАВЛЕНИЯ │
│ ──────────────────────── │
│ 1. Заменить небезопасные строковые функции (D3-TL) │
│ 2. Добавить проверки NULL после выделения памяти (D3-NPC) │
│ 3. Обнулять указатели после освобождения (D3-RN) │
│ 4. Добавить проверки переполнения в вычислениях размеров (D3-IRV) │
│ │
│ Полный отчёт сохранён в: d3fend_audit_2024-12-09.md │
│ │
╰───────────────────────────────────────────────────────────────╯
Программный доступ через API¶
Для автоматизации и интеграции с CI/CD:
from src.security.hardening import HardeningScanner, HardeningCategory
from src.services.cpg import CPGQueryService
# Инициализация сканера
with CPGQueryService() as cpg:
scanner = HardeningScanner(cpg, language="c")
# Запуск всех проверок
findings = scanner.scan_all(limit_per_check=50)
# Или запуск конкретных методик D3FEND
findings = scanner.scan_by_d3fend_id(
["D3-VI", "D3-NPC", "D3-TL"],
limit=30
)
# Или запуск по категории
findings = scanner.scan_by_category(
HardeningCategory.MEMORY_SAFETY,
limit=20
)
# Получение баллов соответствия
scores = scanner.get_compliance_score(findings)
print(f"Общий балл: {scores['overall_score']}%")
print(f"По D3FEND: {scores['d3fend_scores']}")
# Генерация отчёта с рекомендациями по исправлению
report = scanner.get_remediation_report(findings)
with open("hardening_report.md", "w") as f:
f.write(report)
Проверка соответствия нормативным требованиям¶
Сценарий: Аудитор проверяет кодовую базу на соответствие нормативным требованиям.
Шаг 1: Выбор сценария проверки соответствия¶
/select 08
Шаг 2: Проверка стандартов¶
> Проверить на уязвимости из OWASP Top 10
╭─────────────── Аудит OWASP Top 10 ──────────────────────────╮
│ │
│ A01:2021 — Нарушение контроля доступа │
│ ───────────────────────────────── │
│ Статус: 3 находки │
│ - Отсутствует проверка ACL в pg_ls_dir() │
│ - Повышение привилегий через ALTER ROLE │
│ │
│ A02:2021 — Криптографические ошибки │
│ ───────────────────────────────── │
│ Статус: ПРОЙДЕНО │
│ - Используется OpenSSL для шифрования │
│ - scram-sha-256 для аутентификации │
│ │
│ A03:2021 — Инъекции │
│ ──────────────────────── │
│ Статус: 7 находок │
│ - См. отчёт по SQL-инъекциям выше │
│ │
│ A04:2021 — Небезопасное проектирование │
│ ────────────────────────── │
│ Статус: 2 находки │
│ - Суперпользователь по умолчанию без пароля │
│ │
│ Общий балл: 72/100 │
│ │
╰───────────────────────────────────────────────────────────╯
> Найти жёстко заданные учётные данные
> Сгенерировать отчёт о соответствии для CWE-89
Аудит безопасности Python/Django¶
Сценарий: Инженер по безопасности проводит аудит веб-приложения на Django.
При анализе проектов на Python/Django система использует специализированные шаблоны безопасности для обнаружения веб-уязвимостей:
Поддерживаемые уязвимости¶
| Идентификатор | Уязвимость | CWE | Индикаторы |
|---|---|---|---|
| DJANGO_SQL_INJECTION | SQL-инъекция через необработанный запрос | CWE-89 | raw(), extra(), RawSQL(), cursor.execute() |
| DJANGO_XSS | Межсайтовый скриптинг | CWE-79 | mark_safe(), \|safe, autoescape off |
| DJANGO_CSRF | Уязвимость CSRF | CWE-352 | @csrf_exempt |
| DJANGO_AUTH_BYPASS | Обход аутентификации | CWE-287 | @permission_classes([]), AllowAny |
| DJANGO_INSECURE_DESERIALIZE | Небезопасная десериализация | CWE-502 | pickle.loads, yaml.load, eval() |
| DJANGO_PATH_TRAVERSAL | Обход пути | CWE-22 | open(), os.path.join() с пользовательским вводом |
| DJANGO_CMD_INJECTION | Инъекция команд | CWE-78 | subprocess.*, os.system(), shell=True |
| DJANGO_MASS_ASSIGNMENT | Массовое присваивание | CWE-915 | **request.data, update(**kwargs) |
Примеры запросов¶
# Сначала переключитесь на проект Django
/project switch fsin_module
# Затем выберите сценарий аудита безопасности
/select 02
# Задавайте вопросы по безопасности
> Найти SQL-инъекции во вьюхах
> Проверить XSS в шаблонах
> Найти конечные точки без защиты CSRF
> Показать функции, использующие eval() или exec()
Источники заражения (пользовательский ввод)¶
Система отслеживает поток данных из следующих источников Django:
- request.GET.get(), request.POST.get(), request.data.get()
- request.body, request.path, request.FILES
- form.cleaned_data, serializer.validated_data
- Параметры URL (kwargs.get())
Приёмники заражения (опасные функции)¶
Данные, достигающие этих приёмников, помечаются как опасные:
- SQL: raw(), extra(), execute(), RawSQL()
- XSS: mark_safe(), HttpResponse()
- Команды: subprocess.*, os.system(), os.popen()
- Файлы: open(), FileResponse()
- Десериализация: pickle.loads(), yaml.load(), eval(), exec()
Реагирование на инциденты¶
Сценарий: Команда безопасности расследует инцидент.
Шаг 1: Выбор сценария инцидента¶
/select 14
Шаг 2: Трассировка вектора атаки¶
> Проследить вектор атаки от входа до получения административного доступа
╭─────────────── Анализ вектора атаки ────────────────────────╮
│ │
│ Потенциальные пути повышения привилегий: │
│ │
│ Путь 1: SQL-инъекция → Суперпользователь │
│ ───────────────────────────────────── │
│ 1. login() принимает пользовательский ввод │
│ 2. Ввод передаётся в authenticate() │
│ 3. Запрос строится через конкатенацию строк │
│ 4. Инъекция обходит аутентификацию │
│ 5. Сессия получает привилегии суперпользователя │
│ │
│ Путь 2: Перегрузка функций │
│ ──────────────────────────── │
│ 1. Пользователь создаёт функцию с такой же сигнатурой │
│ 2. Манипуляция search_path │
│ 3. Вредоносная функция вызывается суперпользователем │
│ │
│ Меры защиты: │
│ - Параметризованные запросы │
│ - Явная квалификация схемы │
│ - Аудит SECURITY DEFINER │
│ │
╰───────────────────────────────────────────────────────────╯
> Найти пути повышения привилегий
> Показать доступ к данным из скомпрометированной функции
Шаг 3: Оценка последствий¶
> Какие данные можно получить из функции auth_check?
╭─────────────── Оценка последствий ──────────────────────────╮
│ │
│ Функция: auth_check() │
│ Уровень доступа: Контекст суперпользователя │
│ │
│ Достижимые данные: │
│ ──────────────── │
│ │
│ Прямой доступ: │
│ - pg_authid (пароли, роли) │
│ - pg_auth_members (членство в ролях) │
│ - Все пользовательские таблицы │
│ │
│ Через вызовы функций: │
│ - pg_read_file() — доступ к файловой системе │
│ - pg_ls_dir() — просмотр каталога │
│ - COPY TO PROGRAM — выполнение команд │
│ │
│ Радиус поражения: КРИТИЧЕСКИЙ │
│ - Полная компрометация базы данных │
│ - Потенциальный доступ на уровне ОС │
│ │
╰───────────────────────────────────────────────────────────╯
> Найти все вызывающие функции скомпрометированного компонента
Сценарии для технического писателя¶
Генерация документации по API¶
Сценарий: Технический писатель документирует публичное API.
Шаг 1: Выбор сценария документации¶
/select 03
Шаг 2: Генерация документации по функциям¶
> Создай документацию для heap_insert
╭─────────────── Документация API ─────────────────────────╮
│ │
│ ## heap_insert │
│ │
│ Вставляет кортеж в отношение кучи. │
│ │
│ ### Сигнатура │
│ │
│
c │ │ void heap_insert(Relation relation, │ │ HeapTuple tup, │ │ CommandId cid, │ │ int options, │ │ BulkInsertState bistate) │ │
│
│ │
│ ### Параметры │
│ │
│ | Параметр | Тип | Описание │
│ |-----------|---------------|----------------------------│
│ | relation | Relation | Целевое отношение кучи │
│ | tup | HeapTuple | Кортеж для вставки │
│ | cid | CommandId | Идентификатор команды для MVCC │
│ | options | int | Флаги опций вставки │
│ | bistate | BulkInsertState | Состояние массовой вставки │
│ │
│ ### Возвращаемое значение │
│ │
│ void (кортеж модифицируется на месте, при необходимости с присвоением OID) │
│ │
│ ### Пример │
│ │
│
c │ │ HeapTuple tuple = heap_form_tuple(desc, values, nulls); │ │ heap_insert(rel, tuple, GetCurrentCommandId(true), │ │ 0, NULL); │ │
│
│ │
│ ### Смотрите также │
│ │
│ - heap_update() - Обновление существующего кортежа │
│ - heap_delete() - Удаление кортежа │
│ - simple_heap_insert() - Упрощённая обёртка │
│ │
│ ### Исходный код │
│ │
│ src/backend/access/heap/heapam.c:2156 │
│ │
╰───────────────────────────────────────────────────────────╯
> Документируй функции интерфейса SPI
>
>
> Создай справочник API для управления блокировками
Понимание архитектуры модуля¶
Сценарий: Технический писатель документирует архитектуру системы.
> Объясни архитектуру модуля исполнителя (executor)
╭─────────────── Архитектура ──────────────────────────────╮
│ │
│ Архитектура модуля исполнителя (executor) │
│ ══════════════════════════════════════════ │
│ │
│ Назначение: Выполнение планов запросов, созданных планировщиком │
│ │
│ Каталог: src/backend/executor/ │
│ │
│ Основные компоненты: │
│ ──────────────── │
│ │
│ 1. execMain.c - Основные точки входа исполнителя │
│ - ExecutorStart(): Инициализация состояния выполнения │
│ - ExecutorRun(): Основной цикл выполнения │
│ - ExecutorEnd(): Очистка и завершение работы │
│ │
│ 2. execProcnode.c - Диспетчер узлов │
│ - ExecProcNode(): Перенаправление на конкретные типы узлов │
│ - ExecInitNode(): Инициализация узлов плана │
│ - ExecEndNode(): Очистка узлов плана │
│ │
│ 3. Исполнители, специфичные для узлов: │
│ - nodeSeqscan.c - Последовательное сканирование │
│ - nodeIndexscan.c - Сканирование по индексу │
│ - nodeHashjoin.c - Хеш-соединение │
│ - nodeMergejoin.c - Слияние соединений │
│ - nodeAgg.c - Агрегация │
│ - nodeSort.c - Сортировка │
│ │
│ Поток данных: │
│ ────────── │
│ │
│ Дерево плана → Дерево состояния плана → Вывод кортежей │
│ │
│ Зависимости: │
│ ───────────── │
│ → access/ (уровень хранения) │
│ → utils/ (память, кеш) │
│ → nodes/ (определения узлов) │
│ │
╰───────────────────────────────────────────────────────────╯
> Каковы основные компоненты WAL?
>
>
> Как работает MVCC в PostgreSQL?
Создание справочника функций¶
Сценарий: Технический писатель составляет индекс функций.
> Перечисли все публичные функции в модуле исполнителя
╭─────────────── Справочник функций ────────────────────────╮
│ │
│ Публичные функции исполнителя │
│ ════════════════════════════════ │
│ │
│ Точки входа: │
│ ───────────── │
│ ExecutorStart() Инициализация выполнения │
│ ExecutorRun() Выполнение плана │
│ ExecutorFinish() Обработка после выполнения │
│ ExecutorEnd() Очистка │
│ │
│ Операции с узлами: │
│ ──────────────── │
│ ExecProcNode() Выполнить один узел │
│ ExecInitNode() Инициализировать узел │
│ ExecEndNode() Очистить узел │
│ ExecReScan() Сброс для повторного сканирования │
│ │
│ Операции с кортежами: │
│ ───────────────── │
│ ExecStoreTuple() Сохранить кортеж в слоте │
│ ExecClearTuple() Очистить слот │
│ ExecCopySlot() Скопировать содержимое слота │
│ │
│ Всего: 156 публичных функций │
│ │
╰───────────────────────────────────────────────────────────╯
Покажи все точки входа с их сигнатурами
Использование прямого SQL-запроса¶
/query SELECT name, signature, filename FROM nodes_method
WHERE filename LIKE ‘%executor%’
ORDER BY name
LIMIT 20
╭─────────────── Результаты запроса ────────────────────────╮
│ │
│ name | signature | filename │
│ ──────────────────┼────────────────────────┼────────── │
│ ExecAgg | ExecAgg(PlanState*) | nodeAgg.c │
│ ExecAppend | ExecAppend(…) | nodeAppend │
│ ExecBitmapAnd | ExecBitmapAnd(…) | nodeBitma │
│ … | … | … │
│ │
│ Возвращено 20 строк │
│ │
╰───────────────────────────────────────────────────────────╯
Справочник команд TUI¶
Все команды¶
| Команда | Аргументы | Описание |
|---|---|---|
/help |
[команда] |
Показать справку по всем командам или по конкретной команде |
/scenarios |
[группа] |
Список доступных сценариев, с необязательной фильтрацией |
/select |
<номер> |
Выбрать сценарий по номеру (01–16) |
/history |
[количество] |
Показать историю диалога |
/save |
[имя_файла] |
Сохранить текущую сессию |
/load |
<имя_файла> |
Загрузить сохранённую сессию |
/config |
[раздел] [ключ] [значение] |
Просмотр или изменение конфигурации |
/stat |
Показать статистику CPG и ChromaDB | |
/query |
<SQL> |
Выполнить SQL-запрос к базе данных CPG |
/review |
[источник] [id] [--format] [--inline] |
Запустить анализ кода |
/demo |
[--scenarios N,N] [--lang en\|ru] |
Запустить быстрое тестирование |
/clear |
Очистить экран | |
/exit |
Выйти из приложения | |
/project |
[list\|switch\|add] |
Управление проектами CPG |
/cpg |
<подкоманда> [аргументы] |
Операции GoCPG (статистика, запросы, ветки, хуки, мониторинг) |
/explain |
<имя_метода> [--depth N] [--format json\|rich] |
Комплексный анализ метода |
/watch |
<start\|stop\|status> [путь] |
Панель наблюдения с метриками и оповещениями |
Подробное описание команд¶
/project¶
Управление несколькими проектами CPG (переключение между разными кодовыми базами).
# Показать информацию о текущем проекте
/project
# Список всех доступных проектов
/project list
# Переключиться на другой проект
/project switch fsin_module
/project switch postgresql
# Добавить новый проект
/project add myproject path/to/project.duckdb python "Мой Python-проект"
Конфигурация проектов (projects.yaml):
projects:
postgresql:
db_path: "data/projects/postgres.duckdb"
language: c
description: "Исходный код PostgreSQL 17"
fsin_module:
db_path: "workspace/fsin_module_v2.duckdb"
language: python
description: "Django-модуль FSIN"
active_project: postgresql
Автоматическое переключение доменов:
При смене проекта система автоматически активирует соответствующий доменный плагин:
| Язык | Доменный плагин | Шаблоны безопасности |
|---|---|---|
| c, cpp | postgresql / generic_cpp | Безопасность памяти, переполнение буфера |
| python | python_django | SQL-инъекции, XSS, CSRF |
# Пример: переключение на проект Python/Django
/project switch fsin_module
# Вывод: Домен активирован: python_django
# Пример: возврат к проекту на C
/project switch postgresql
# Вывод: Домен активирован: postgresql
/cpg¶
Операции GoCPG — взаимодействие с движком графа кода непосредственно из TUI.
# Показать справку
/cpg
# Статистика CPG
/cpg stats
/cpg stats data/projects/postgres.duckdb
# Выполнение SQL-запроса
/cpg query SELECT COUNT(*) FROM nodes_method
/cpg query SELECT full_name FROM nodes_method LIMIT 10
# Список языковых модулей
/cpg frontends
# Управление ветками
/cpg branches # Список отслеживаемых веток
/cpg branches switch feature-x # Переключить активную ветку
/cpg branches prune # Удалить устаревшие ветки
# Управление git-хуками
/cpg hooks status # Показать статус хуков
/cpg hooks install # Установить git-хуки
/cpg hooks uninstall # Удалить git-хуки
# Управление индексами
/cpg index # Создать/пересоздать индексы DuckDB
# Валидация метрик
/cpg metrics
/cpg metrics /path/to/source
# Управление подмодулями
/cpg submodules # Список отслеживаемых подмодулей
/cpg submodules prune # Удалить устаревшие подмодули
# Поиск структурных паттернов
/cpg search "malloc($x)" --lang c # Ad-hoc поиск паттернов (без CPG-базы)
/cpg search "if ($cond) { return $x; }" --lang c --max-results 20
# Сканирование структурных паттернов (с CPG-ограничениями, использует правила)
/cpg scan # Сканирование по всем правилам
/cpg scan --rule unchecked-return # Сканирование по конкретному правилу
/cpg scan --severity high # Фильтрация по серьёзности
# Мониторинг файлов
/cpg watch start /path/to/source # Начать мониторинг изменений
/cpg watch stop # Остановить мониторинг
| Подкоманда | Аргументы | Описание |
|---|---|---|
stats |
[путь_к_db] |
Статистика CPG: количество узлов/рёбер, размер БД |
query |
<sql> |
Выполнение SQL-запроса к базе данных CPG |
frontends |
Список доступных языковых модулей | |
branches |
[list\|switch ИМЯ\|prune] |
Управление отслеживаемыми ветками CPG |
hooks |
[status\|install\|uninstall] |
Управление git-хуками для автообновления CPG |
index |
[путь_к_db] |
Создание/пересоздание индексов DuckDB |
metrics |
[путь] |
Валидация метрик |
submodules |
[list\|prune] |
Управление отслеживаемыми подмодулями |
search |
<шаблон> --lang ЯЗЫК |
Ad-hoc поиск структурных шаблонов (без CPG-базы) |
scan |
[--rule ID] [--severity УРОВЕНЬ] |
Сканирование шаблонов с CPG-ограничениями по YAML-правилам |
watch |
[start <путь>\|stop] |
Мониторинг файлов для обновления CPG в реальном времени |
/explain¶
Комплексный анализ метода — метрики, граф вызовов, флаги безопасности и информация о подсистеме в одном представлении.
# Базовый анализ метода
/explain heap_insert
# Увеличить глубину обхода вызывающих
/explain ExecCreateTable --depth 3
# Вывод в формате JSON (для скриптов или MCP)
/explain palloc --format json
Выводимая информация:
| Раздел | Детали |
|---|---|
| Идентификация | Полное имя, путь к файлу, диапазон строк |
| Метрики | Цикломатическая сложность, уровень риска, входящая/исходящая связность |
| Граф вызовов | Прямые вызывающие, транзитивное количество, прямые вызываемые |
| Безопасность | Флаги taint source/sink, пути потока данных через метод |
| Контекст | Подсистема, флаги шаблонов (deprecated, debug, todo) |
Пример вывода:
╭──────────────── Метод: heap_insert ──────────────────╮
│ │
│ Файл: src/backend/access/heap/heapam.c │
│ Строки: 1842–1956 (114 строк) │
│ Сложность: 12 (Средний риск) │
│ Fan-in: 24 Fan-out: 8 │
│ │
│ Вызывающие (прямые): ExecInsert, simple_heap_insert │
│ Вызываемые (прямые): heap_prepare_insert, ... │
│ Taint: source=нет sink=нет │
│ Подсистема: access/heap │
│ │
╰──────────────────────────────────────────────────────╯
Если метод не найден, /explain предлагает похожие имена через нечёткий поиск:
Метод не найден: hepa_insert
Возможно, вы имели в виду:
/explain heap_insert
/explain heap_inplace
/explain heap_delete
/watch¶
Панель наблюдения в реальном времени — подписывается на события gocpg watch и отображает дельты метрик, новые пути распространения данных и оповещения.
# Запустить панель наблюдения
/watch start /путь/к/исходникам
# Проверить статус панели
/watch status
# Остановить панель наблюдения
/watch stop
При запуске панель:
- Запускает webhook-приёмник на
127.0.0.1(порт изconfig.yaml→watch_dashboard.webhook_port, по умолчанию 8765) - Запускает подпроцесс
gocpg watchс указанием webhook - Отображает Rich Live layout с панелями: - Изменённые методы — дельты сложности с цветовой индикацией - Пути распространения данных — новые taint-пути через изменённый код - Оповещения — пороговые оповещения для пиков сложности, входящая связность и новых taint-путей
Конфигурация в config.yaml:
watch_dashboard:
webhook_port: 8765
debounce_ms: 1000
complexity_warning: 15
complexity_critical: 25
new_taint_path_alert: true
fan_in_warning: 20
panels:
- changed_methods
- taint_paths
- metrics_summary
/scenarios¶
# Показать все сценарии
/scenarios
# Фильтрация по группе
/scenarios security # Сценарии, связанные с безопасностью
/scenarios dev # Сценарии разработки
/scenarios qa # Сценарии обеспечения качества
/select¶
# Выбор по номеру
/select 1 # Онбординг
/select 02 # Аудит безопасности
/select 15 # Отладка
/config¶
# Показать все разделы конфигурации
/config
# Показать конкретный раздел
/config llm
# Установить значение
/config llm temperature 0.7
/config llm provider gigachat
/query¶
# Простые запросы
/query SELECT COUNT(*) FROM nodes_method
/query SELECT name, filename FROM nodes_method WHERE name LIKE 'heap%'
# Описание таблиц
/query DESCRIBE nodes_method
/query SHOW TABLES
# Сложные запросы
/query SELECT caller.name, callee.name
FROM edges_call e
JOIN nodes_method caller ON e.src = caller.id
JOIN nodes_method callee ON e.dst = callee.id
WHERE callee.name = 'palloc'
LIMIT 10
/review¶
# Интерактивный режим (выбор источника)
/review
# GitHub PR
/review github 123
/review github 123 --format json
# GitLab MR
/review gitlab 456 --inline
# Локальные изменения в git
/review git
/review git --format yaml
# Файл изменений
/review file changes.patch --format md --inline
Руководство по настройке¶
Настройка поставщика LLM¶
GigaChat (Sber)¶
# config.yaml
llm:
provider: "gigachat"
gigachat:
credentials: ${GIGACHAT_AUTH_KEY}
model: "GigaChat-2" # или GigaChat-2-Pro, GigaChat-2-Max
temperature: 0.7
# Переменная окружения
export GIGACHAT_AUTH_KEY="ваш-ключ-в-base64"
OpenAI¶
# config.yaml
llm:
provider: "openai"
openai:
api_key: ${OPENAI_API_KEY}
model: "gpt-4"
temperature: 0.7
# Переменная окружения
export OPENAI_API_KEY="sk-..."
Локальная модель (llama.cpp)¶
# config.yaml
llm:
provider: "local"
local:
model_path: ${QWEN3_MODEL_PATH}
n_gpu_layers: -1 # Все слои на GPU
n_ctx: 8192
Настройки поиска¶
retrieval:
embedding_model: "all-MiniLM-L6-v2"
top_k_qa: 3 # Количество извлекаемых примеров вопросов и ответов
max_results: 50 # Максимальное количество результатов поиска
Ограничения запросов¶
query:
default_limit: 100 # Значение LIMIT по умолчанию для SQL
max_limit: 1000 # Максимально допустимое значение LIMIT
Приложение: Все 21 сценарий¶
| № | Название | Для кого подходит | Пример запроса |
|---|---|---|---|
| 01 | Онбординг | Новые разработчики | “Где определена функция X?” |
| 02 | Аудит безопасности | Команда безопасности | “Найти уязвимости к SQL-инъекциям” |
| 03 | Документация | Технические писатели | “Создать документацию для функции X” |
| 04 | Разработка функций | Добавление новых возможностей | “Куда добавить новый хук?” |
| 05 | Рефакторинг | Очистка кода | “Найти неиспользуемый код в модуле X” |
| 06 | Производительность | Оптимизация | “Найти узкие места в производительности” |
| 07 | Покрытие тестами | Команда тестирования | “Какие функции не покрыты тестами?” |
| 08 | Соответствие требованиям | Аудиторы | “Проверить соответствие OWASP Top 10” |
| 09 | Проверка кода | Рецензенты | “Проверить эти изменения” |
| 10 | Межрепозиторные связи | Архитекторы | “Найти зависимости между репозиториями” |
| 11 | Архитектура | Архитекторы | “Найти нарушения уровневой архитектуры” |
| 12 | Технический долг | Менеджеры | “Оценить объём технического долга” |
| 13 | Массовый рефакторинг | Крупные изменения | “Переименовать все X в Y” |
| 14 | Реагирование на инциденты | Безопасность | “Отследить вектор атаки” |
| 15 | Отладка | Разработчики | “Найти точки для отладки” |
| 16 | Точки входа | Безопасность | “Перечислить все конечные точки API” |
| 17 | Редактирование файлов | Разработчики | “Редактировать функцию validate_input” |
| 18 | Оптимизация кода | Разработчики | “Оптимизировать модуль аутентификации” |
| 19 | Проверка стандартов | QA/Соответствие | “Проверить по company_standards.yaml” |
| 20 | Зависимости | Безопасность/DevOps | “Сканировать на уязвимые пакеты” |
| 21 | Поиск шаблонов | Безопасность/QA | “Найти непроверённые возвращаемые значения” |
Руководство по выбору сценариев¶
Для разработчиков: - Первый день: Сценарий 01 (Онбординг) - Разработка функций: Сценарий 04 (Разработка функций) - Исправление ошибок: Сценарий 15 (Отладка) - Очистка кода: Сценарий 05 (Рефакторинг) - Редактирование кода: Сценарий 17 (Редактирование файлов) - Оптимизация: Сценарий 18 (Оптимизация кода)
Для QA / тестировщиков: - Пробелы в покрытии: Сценарий 07 (Покрытие тестами) - Проверка кода: Сценарий 09 (Проверка кода) - Метрики качества: Сценарий 12 (Технический долг) - Стандарты: Сценарий 19 (Проверка стандартов)
Для специалистов по безопасности / DevOps: - Поиск уязвимостей: Сценарий 02 (Аудит безопасности) - Соответствие стандартам: Сценарий 08 (Соответствие требованиям) - Инциденты: Сценарий 14 (Реагирование на инциденты) - Атакуемая поверхность: Сценарий 16 (Точки входа) - Зависимости: Сценарий 20 (Зависимости) - Поиск шаблонов: Сценарий 21 (Поиск шаблонов)
Для технических писателей: - Документация API: Сценарий 03 (Документация) - Архитектура: Сценарий 11 (Архитектура) - Межрепозиторные связи: Сценарий 10 (Межрепозиторные связи)
Отчёты о проверке безопасности (CLI)¶
Обзор¶
CodeGraph предоставляет инструмент командной строки (CLI) для создания полных отчётов о проверке безопасности.
Отчёты могут быть сгенерированы в нескольких форматах (Markdown, JSON, SARIF) с поддержкой локализации (английский, русский).
Сценарий: Проверка безопасности проекта на Django¶
Ситуация: Инженеру по безопасности необходимо проверить проект на Django перед развертыванием в рабочей среде.
Шаг 1: Выполнение полного сканирования безопасности¶
python -m src.cli.security_audit full \
--path /path/to/django/project \
--output-dir ./security_reports \
--language ru
Шаг 2: Просмотр сгенерированного отчёта¶
Инструмент создаёт три файла:
security_report.md— читаемый отчёт в формате Markdownsecurity_report.json— машинно-читаемый JSON для CI/CDsecurity_report.sarif— формат GitHub Security Alerts
Пример вывода (Markdown)¶
# Отчёт по безопасности: My Django Project
**Путь к проекту:** `/path/to/django/project`
**Время аудита:** 2025-12-09 20:43:19
**Проанализировано файлов:** 88
Краткое резюме¶
| Серьёзность | Количество |
|---|---|
| 🔴 КРИТИЧЕСКИЙ | 2 |
| 🟠 ВЫСОКИЙ | 6 |
| 🟡 СРЕДНИЙ | 2 |
🔴 КРИТИЧЕСКИЙ уровень уязвимости (2)¶
1. SECRET_KEY с резервным значением (сканирование файлов)¶
Файл: backend/settings.py:25
CWE: CWE-798
Описание: SECRET_KEY имеет небезопасное резервное (fallback) значение
Уязвимый код:
SECRET_KEY = os.environ.get('SECRET_KEY', 'insecure-fallback')
Рекомендация:
Удалите резервное значение: SECRET_KEY = os.environ["SECRET_KEY"]
Сценарий: Быстрая проверка безопасности¶
Ситуация: Разработчик хочет выполнить быструю проверку на уязвимости перед коммитом.
python -m src.cli.security_audit quick --path .
╭─────────────────── Результаты быстрой проверки ───────────────────╮
│ │
│ Проверено файлов: 45 │
│ Время: 0.3с │
│ │
│ Обнаружено: │
│ 🔴 Критические: 0 │
│ 🟠 Высокие: 2 │
│ 🟡 Средние: 1 │
│ │
│ Запустите 'security-audit full', чтобы получить подробный отчёт │
│ │
╰─────────────────────────────────────────────────────────────────╯
Сценарий: Интеграция в CI/CD¶
Ситуация: Добавление проверок безопасности в конвейер GitLab CI.
.gitlab-ci.yml¶
security-audit:
stage: test
script:
- pip install -r requirements.txt
- python -m src.cli.security_audit full \
--path . \
--output-dir ./security_reports \
--format json,sarif
- |
CRITICAL=$(jq '.summary.critical_issues' security_reports/security_report.json)
if [ "$CRITICAL" -gt 0 ]; then
echo "Обнаружены критические уязвимости!"
exit 1
fi
artifacts:
paths:
- security_reports/
reports:
sast: security_reports/security_report.sarif
Программное использование¶
Ситуация: Генерация отчётов из кода на Python.
from src.security.file_scanner import FileSecurityScanner
from src.security.report_generator import ReportGenerator
# Инициализация сканера
scanner = FileSecurityScanner()
# Запуск сканирования
result = scanner.scan_project('/path/to/project')
# Генерация отчёта
generator = ReportGenerator()
report = generator.create_report(
project_name='My Project',
project_path=result.project_path,
scan_result=result
)
# Сохранение в нескольких форматах
output_files = generator.save_report(
output_dir='./reports',
formats=['markdown', 'json', 'sarif'],
language='ru' # Локализация на русский язык
)
print(f"Отчёт сохранён в: {output_files['markdown']}")
Обнаруживаемые шаблоны уязвимостей¶
Сканер безопасности выявляет шаблоны, специфичные для Django/Python:
| ID шаблона | Уровень серьёзности | Описание |
|---|---|---|
| FILE_SECRET_FALLBACK_001 | Критический | SECRET_KEY с небезопасным резервным значением |
| FILE_DJANGO_DEBUG_001 | Критический | DEBUG=True в рабочей среде |
| FILE_CORS_001 | Высокий | CORS_ALLOW_ALL_ORIGINS=True |
| FILE_HOSTS_001 | Высокий | ALLOWED_HOSTS=[‘*’] |
| FILE_DB_001 | Высокий | Стандартный пароль базы данных |
| FILE_JWT_001 | Высокий | Срок действия JWT-токена > 24 часов |
| FILE_PATH_001 | Высокий | Риск перехода по путям (path traversal) |
| FILE_DEBUG_PERM_001 | Высокий | Права доступа зависят от DEBUG |
| FILE_TOOLBAR_001 | Средний | Debug toolbar включён безусловно |
| FILE_PAGESIZE_001 | Средний | PAGE_SIZE > 1000 (риск DoS) |
Раздел соответствия D3FEND¶
Отчёты включают соответствие стандарту MITRE D3FEND по повышению защищённости исходного кода:
Соответствие D3FEND укреплению исходного кода¶
| Техника | Название | Статус | Применимость |
|---|---|---|---|
| D3-CS | Очистка учётных данных | ✅ | Применимо для Python |
| D3-DLV | Валидация доменной логики | ✅ | Применимо для Python |
| D3-OLV | Валидация операционной логики | ✅ | Применимо для Python |
| D3-VI | Инициализация переменных | N/A | Только C/C++ |
Общий показатель соответствия: 100% (3/3 применимых техник)
Типовые рабочие процессы¶
Ежедневная проверка безопасности¶
# Утренний анализ безопасности
/select 02
> Найти уязвимости в недавно изменённых файлах
/review git
/exit
Еженедельная проверка качества кода¶
# Еженедельный анализ качества
/select 05
> Найти неиспользуемый код, появившийся на этой неделе
/select 12
> Показать сводку по техническому долгу
/select 07
> Какие новые функции не покрыты тестами?
Аудит перед релизом¶
# Перед основным релизом
/select 08
> Сгенерировать отчёт о соответствии OWASP Top 10
/select 02
> Найти все критические уязвимости
/review git --format json > audit_report.json
Онбординг нового разработчика¶
# Настройка первого дня
/select 01
> Объясни общую архитектуру
> Какие основные подсистемы существуют?
> С какого места лучше начать изучение кода?
/save onboarding_session
Темы¶
Доступные темы¶
| Тема | Описание |
|---|---|
| default | Акценты бирюзового цвета, сбалансированный контраст |
| dark | Акценты пурпурного цвета, подходит для тёмного фона |
| light | Акценты синего цвета, подходит для светлого терминала |
Использование тем¶
# Через командную строку
python -m src.tui.app --theme dark
# В config.yaml
tui:
theme: dark
Элементы темы¶
Темы настраивают: - Цвета заголовка и подзаголовка - Цвета сообщений (пользователя, ассистента, системы, ошибки) - Цвета рамок - Индикаторы сценариев - Подсветку кода - Индикаторы выполнения
Сессии¶
Автоматическое управление сессиями¶
Сессии автоматически: - Создаются при запуске TUI - Сохраняются периодически во время использования - Сохраняются при выходе
Ручное управление сессиями¶
/save # Сохранить текущую сессию
/save analysis_v2 # Сохранить с указанием пользовательского имени
/load # Вывести список сессий
/load analysis_v2 # Загрузить конкретную сессию
Содержимое сессии¶
Сессии содержат: - Историю диалога - Текущий сценарий - Состояние конфигурации - Контекст проекта - Метаданные (временные метки, количество сообщений)
Расположение хранилища сессий¶
По умолчанию: ./sessions/
Пользовательский путь: python -m src.tui.app --session-dir /путь/к/сессиям
Советы и рекомендации¶
Горячие клавиши¶
| Клавиша | Действие |
|---|---|
| Ctrl+C | Отменить текущий ввод |
| Ctrl+D | Выйти (с подтверждением) |
| Стрелка вверх | Предыдущая команда (readline) |
| Стрелка вниз | Следующая команда (readline) |
Псевдонимы команд¶
| Псевдоним | Команда |
|---|---|
| /h | /help |
| /q | /exit |
| /quit | /exit |
| /stats | /stat |
| /sql | /query |
| /proj | /project |
| /grp | /group |
| /sess | /session |
| /whoami | /auth me |
Эффективные рабочие процессы¶
Быстрый аудит безопасности:
/select 2
Найти уязвимости к SQL-инъекциям
Найти риски командных инъекций
Найти уязвимости к XSS
Исследование кода:
/select 1
Что делает функция main?
Покажи граф вызовов для функции X
Процесс проверки кода:
/review git
# Просмотр результатов
/save security_review_dec9
Советы по запросам¶
- Будьте конкретны: “Найти SQL-инъекции в модуле аутентификации” лучше, чем “Найти SQL-инъекции”
- Используйте контекст сценария: Выберите подходящий сценарий перед выполнением запроса
- Сначала проверьте статистику: Используйте
/stat, чтобы понять размер базы данных - Используйте SQL для точности:
/query SELECT * FROM nodes_method WHERE name LIKE '%auth%'
Устранение неполадок¶
Распространённые проблемы¶
«Copilot недоступен»¶
Причина: ChromaDB не установлен или инициализация не удалась.
Решения:
pip install chromadb
# или
pip install -r requirements.txt
«База данных не найдена»¶
Причина: Отсутствует база данных CPG.
Решения: 1. Импортируйте проект:
bash
python -m src.cli.import_commands full --path ./mycode
- Проверьте конфигурацию проекта:
bash
/project list
«Ошибка поставщика LLM»¶
Причина: Отсутствуют учётные данные API.
Решения: 1. Проверьте переменные окружения:
bash
echo $GIGACHAT_CREDENTIALS
echo $OPENAI_API_KEY
- Проверьте config.yaml:
bash
/config llm
Медленные ответы¶
Причина: Большая база данных или задержка в сети.
Решения:
1. Проверьте статистику базы данных: /stat
2. Используйте более конкретные запросы
3. Рассмотрите возможность использования локального поставщика LLM
4. Уменьшите размер контекста в config.yaml:
yaml
llm:
local:
n_ctx: 4096 # Уменьшить с 8192
Проблемы с кодировкой символов (Windows)¶
Причина: Несоответствие кодировки терминала.
Решения:
# Установите UTF-8 в PowerShell
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# Или используйте Windows Terminal (рекомендуется)
Режим отладки¶
Включите логирование отладки для диагностики:
python -m src.tui.app --debug
Это позволяет увидеть: - Вызовы API LLM - Запросы к базе данных - Операции поиска - Трассировки ошибок
Файлы журналов (логов)¶
Журналы записываются в файл logs/tui.log (если настроено).
Получение помощи¶
- Введите
/helpдля справки по командам - Введите
/help <команда>для справки по конкретной команде - Проверьте логи в каталоге
logs/ - Сообщите о проблемах: https://github.com/anthropics/claude-code/issues
Смотрите также¶
- Руководство CLI — Интерфейс командной строки
- Сценарии — Использование сценариев в программном коде
- REST API — Справочник по HTTP API
- Безопасность — Функции безопасности
Создано для CodeGraph v1.0