Перейти к основному содержимому

Oss Forensics

Расследование цепочек поставок, восстановление улик и криминалистический анализ репозиториев GitHub. Включает восстановление удалённых коммитов, обнаружение force-push, извлечение индикаторов компрометации (IOC), сбор доказательств из нескольких источников, формирование и проверку гипотез, а также структурированную криминалистическую отчётность. Вдохновлено системой OSS Forensics из RAPTOR (более 1800 строк).

Метаданные навыка​

ИсточникОпционально — установка через vibeos skills install official/security/oss-forensics
Путьoptional-skills/security/oss-forensics
Платформыlinux, macos, windows

Справочник: полный SKILL.md​

к сведению

Ниже приведено полное определение навыка, которое VibeOS загружает при его активации. Это те инструкции, которые видит агент, когда навык активен.

Навык криминалистики безопасности OSS

Семифазная мультиагентная система расследования для изучения атак на цепочки поставок открытого ПО. Адаптировано из криминалистической системы RAPTOR. Охватывает GitHub Archive, Wayback Machine, GitHub API, локальный анализ git, извлечение IOC, формирование и проверку гипотез на основе доказательств, и финальную генерацию криминалистического отчёта.


⚠️ Защитные барьеры против галлюцинаций​

Прочитайте их перед каждым шагом расследования. Их нарушение делает отчёт недействительным.

  1. Правило «Сначала доказательства»: Каждое утверждение в любом отчёте, гипотезе или сводке ОБЯЗАННО ссылаться как минимум на один идентификатор доказательства (EV-XXXX). Утверждения без цитирования запрещены.
  2. НЕ ВЫХОДИ ЗА РАМКИ: Каждый подагент (исследователь) имеет один источник данных. НЕ смешивайте источники. Исследователь GH Archive не запрашивает GitHub API, и наоборот. Границы ролей жёсткие.
  3. Разделение фактов и гипотез: Все непроверенные выводы помечайте как [HYPOTHESIS]. Только утверждения, подтверждённые исходными источниками, могут быть представлены как факты.
  4. Запрет на фабрикацию доказательств: Валидатор гипотез ОБЯЗАН механически проверить, что каждый указанный идентификатор доказательства действительно существует в хранилище доказательств, прежде чем принять гипотезу.
  5. Опровержение требует доказательств: Гипотеза не может быть отклонена без конкретного, подтверждённого доказательствами контраргумента. «Доказательств не найдено» недостаточно для опровержения — это лишь делает гипотезу неубедительной.
  6. Двойная проверка SHA/URL: Любой SHA коммита, URL или внешний идентификатор, указанный как доказательство, должен быть независимо подтверждён как минимум из двух источников, прежде чем быть помеченным как проверенный.
  7. Правило подозрительного кода: Никогда не запускайте код, найденный в исследуемом репозитории, локально. Анализируйте только статически или используйте execute_code в изолированной среде.
  8. Редактирование секретов: Любые ключи API, токены или учётные данные, обнаруженные в ходе расследования, должны быть отредактированы в финальном отчёте. Внутренне логируйте их без редактирования.

Примеры сценариев​

  • Сценарий A: Путаница зависимостей: Вредоносный пакет internal-lib-v2 загружен на NPM с более высокой версией, чем внутренняя. Следователь должен отследить, когда этот пакет был впервые замечен, и были ли в целевом репозитории PushEvents, обновляющие package.json до этой версии.
  • Сценарий B: Захват мейнтейнера: Учётная запись давнего контрибьютора используется для пуша бэкдорированного .github/workflows/build.yml. Следователь ищет PushEvents от этого пользователя после длительного периода бездействия или с нового IP/местоположения (если это обнаружимо через BigQuery).
  • Сценарий C: Сокрытие через force-push: Разработчик случайно коммитит секрет продакшена, а затем делает force-push, чтобы «исправить» это. Следователь использует git fsck и GH Archive для восстановления исходного SHA коммита и проверки того, что было раскрыто.

Соглашение о путях: В рамках этого навыка SKILL_DIR означает корень директории установки этого навыка (папку, содержащую этот SKILL.md). При загрузке навыка разрешайте SKILL_DIR в фактический путь — например, ~/.vibeos/skills/security/oss-forensics/ или эквивалент optional-skills/. Все ссылки на скрипты и шаблоны относительны него.

Фаза 0: Инициализация​

  1. Создайте рабочую директорию расследования:
    mkdir investigation_$(echo "REPO_NAME" | tr '/' '_')
    cd investigation_$(echo "REPO_NAME" | tr '/' '_')
  2. Инициализируйте хранилище доказательств:
    python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list
  3. Скопируйте шаблон криминалистического отчёта:
    cp SKILL_DIR/templates/forensic-report.md ./investigation-report.md
  4. Создайте файл iocs.md для отслеживания индикаторов компрометации по мере их обнаружения.
  5. Запишите время начала расследования, целевой репозиторий и заявленную цель расследования.

Фаза 1: Разбор запроса и извлечение IOC​

Цель: Извлечь все структурированные цели расследования из запроса пользователя.

Действия:

  • Разберите запрос пользователя и извлеките:
    • Целевой репозиторий (owner/repo)
    • Целевых акторов (хендлы GitHub, адреса электронной почты)
    • Временное окно интереса (диапазоны дат коммитов, временные метки PR)
    • Предоставленные индикаторы компрометации: SHA коммитов, пути к файлам, имена пакетов, IP-адреса, домены, ключи API/токены, вредоносные URL
    • Любые связанные отчёты безопасности вендоров или посты в блогах

Инструменты: Только рассуждение или execute_code для извлечения по регулярным выражениям из больших текстовых блоков.

Результат: Заполните iocs.md извлечёнными IOC. Каждый IOC должен иметь:

  • Тип (из: COMMIT_SHA, FILE_PATH, API_KEY, SECRET, IP_ADDRESS, DOMAIN, PACKAGE_NAME, ACTOR_USERNAME, MALICIOUS_URL, OTHER)
  • Значение
  • Источник (предоставлено пользователем, выведено)

Справочник: См. evidence-types.md для таксономии IOC.


Фаза 2: Параллельный сбор доказательств​

Запустите до 5 специализированных подагентов-исследователей, используя delegate_task (пакетный режим, макс. 3 одновременно). Каждый исследователь имеет один источник данных и не должен смешивать источники.

Примечание для оркестратора: Передайте список IOC из Фазы 1 и временное окно расследования в поле context каждой делегированной задачи.


Исследователь 1: Локальный git-исследователь​

ГРАНИЦА РОЛИ: Вы запрашиваете ТОЛЬКО ЛОКАЛЬНЫЙ GIT-РЕПОЗИТОРИЙ. Не вызывайте никаких внешних API.

Действия:

# Клонировать репозиторий
git clone https://github.com/OWNER/REPO.git target_repo && cd target_repo

# Полный лог коммитов со статистикой
git log --all --full-history --stat --format="%H|%ae|%an|%ai|%s" > ../git_log.txt

# Обнаружение признаков force-push (осиротевшие/висячие коммиты)
git fsck --lost-found --unreachable 2>&1 | grep commit > ../dangling_commits.txt

# Проверка reflog на переписанную историю
git reflog --all > ../reflog.txt

# Список ВСЕХ веток, включая удалённые удалённые ссылки
git branch -a -v > ../branches.txt

# Поиск подозрительных добавлений больших бинарных файлов
git log --all --diff-filter=A --name-only --format="%H %ai" -- "*.so" "*.dll" "*.exe" "*.bin" > ../binary_additions.txt

# Проверка аномалий GPG-подписей
git log --show-signature --format="%H %ai %aN" > ../signature_check.txt 2>&1

Доказательства для сбора (добавить через python3 SKILL_DIR/scripts/evidence-store.py add):

  • Каждый SHA висячего коммита → тип: git
  • Признаки force-push (reflog, показывающий переписывание истории) → тип: git
  • Неподписанные коммиты от проверенных контрибьюторов → тип: git
  • Подозрительные добавления бинарных файлов → тип: git

Справочник: См. recovery-techniques.md для доступа к коммитам, сделанным через force-push.


Исследователь 2: Исследователь GitHub API​

ГРАНИЦА РОЛИ: Вы запрашиваете ТОЛЬКО GITHUB REST API. Не запускайте git-команды локально.

Действия:

# Коммиты (с пагинацией)
curl -s "https://api.github.com/repos/OWNER/REPO/commits?per_page=100" > api_commits.json

# Pull Requests, включая закрытые/удалённые
curl -s "https://api.github.com/repos/OWNER/REPO/pulls?state=all&per_page=100" > api_prs.json

# Issues
curl -s "https://api.github.com/repos/OWNER/REPO/issues?state=all&per_page=100" > api_issues.json

# Контрибьюторы и изменения коллабораторов
curl -s "https://api.github.com/repos/OWNER/REPO/contributors" > api_contributors.json

# События репозитория (последние 300)
curl -s "https://api.github.com/repos/OWNER/REPO/events?per_page=100" > api_events.json

# Проверка деталей конкретного подозрительного SHA коммита
curl -s "https://api.github.com/repos/OWNER/REPO/git/commits/SHA" > commit_detail.json

# Релизы
curl -s "https://api.github.com/repos/OWNER/REPO/releases?per_page=100" > api_releases.json

# Проверка существования конкретного коммита (коммиты, сделанные через force-push, могут выдавать 404 на commits/, но успешно проходить на git/commits/)
curl -s "https://api.github.com/repos/OWNER/REPO/commits/SHA" | jq .sha

Цели для перекрёстной проверки (помечайте расхождения как доказательства):

  • PR существует в архиве, но отсутствует в API → доказательство удаления
  • Контрибьютор в событиях архива, но не в списке контрибьюторов → доказательство отзыва разрешений
  • Коммит в PushEvents архива, но не в списке коммитов API → доказательство force-push/удаления

Справочник: См. evidence-types.md для типов событий GH.


Исследователь 3: Исследователь Wayback Machine​

ГРАНИЦА РОЛИ: Вы запрашиваете ТОЛЬКО CDX API WAYBACK MACHINE. Не используйте GitHub API.

Цель: Восстановить удалённые страницы GitHub (README, issues, PR, релизы, вики-страницы).

Действия:

# Поиск архивных снимков главной страницы репозитория
curl -s "https://web.archive.org/cdx/search/cdx?url=github.com/OWNER/REPO&output=json&limit=100&from=YYYYMMDD&to=YYYYMMDD" > wayback_main.json

# Поиск конкретного удалённого issue
curl -s "https://web.archive.org/cdx/search/cdx?url=github.com/OWNER/REPO/issues/NUM&output=json&limit=50" > wayback_issue_NUM.json

# Поиск конкретного удалённого PR
curl -s "https://web.archive.org/cdx/search/cdx?url=github.com/OWNER/REPO/pull/NUM&output=json&limit=50" > wayback_pr_NUM.json

# Получение лучшего снимка страницы
# Используйте URL Wayback Machine: https://web.archive.org/web/TIMESTAMP/ORIGINAL_URL
# Пример: https://web.archive.org/web/20240101000000*/github.com/OWNER/REPO

# Расширенный: Поиск удалённых релизов/тегов
curl -s "https://web.archive.org/cdx/search/cdx?url=github.com/OWNER/REPO/releases/tag/*&output=json" > wayback_tags.json

# Расширенный: Поиск исторических изменений вики
curl -s "https://web.archive.org/cdx/search/cdx?url=github.com/OWNER/REPO/wiki/*&output=json" > wayback_wiki.json

Доказательства для сбора:

  • Архивные снимки удалённых issues/PR с их содержимым
  • Исторические версии README, показывающие изменения
  • Доказательства контента, присутствующего в архиве, но отсутствующего в текущем состоянии GitHub

Справочник: См. github-archive-guide.md для параметров CDX API.


Исследователь 4: Исследователь GH Archive / BigQuery​

ГРАНИЦА РОЛИ: Вы запрашиваете ТОЛЬКО GITHUB ARCHIVE ЧЕРЕЗ BIGQUERY. Это защищённая от несанкционированного доступа запись всех публичных событий GitHub.

Предварительные требования: Требуются учётные данные Google Cloud с доступом к BigQuery (gcloud auth application-default login). Если они недоступны, пропустите этого исследователя и отметьте это в отчёте.

Правила оптимизации затрат (ОБЯЗАТЕЛЬНЫ):

  1. ВСЕГДА запускайте --dry_run перед каждым запросом для оценки стоимости.
  2. Используйте _TABLE_SUFFIX для фильтрации по диапазону дат и минимизации сканируемых данных.
  3. SELECT только те столбцы, которые вам нужны.
  4. Добавляйте LIMIT, если не выполняете агрегацию.
# Шаблон: безопасный запрос BigQuery для PushEvents в OWNER/REPO
bq query --use_legacy_sql=false --dry_run "
SELECT created_at, actor.login, payload.commits, payload.before, payload.head,
payload.size, payload.distinct_size
FROM \`githubarchive.month.*\`
WHERE _TABLE_SUFFIX BETWEEN 'YYYYMM' AND 'YYYYMM'
AND type = 'PushEvent'
AND repo.name = 'OWNER/REPO'
LIMIT 1000
"
# Если стоимость приемлема, выполните повторно без --dry_run

# Обнаружение force-push: PushEvents с нулевым distinct_size означают, что коммиты были принудительно стёрты
# payload.distinct_size = 0 AND payload.size > 0 → индикатор force push

# Проверка событий удаления веток
bq query --use_legacy_sql=false "
SELECT created_at, actor.login, payload.ref, payload.ref_type
FROM \`githubarchive.month.*\`
WHERE _TABLE_SUFFIX BETWEEN 'YYYYMM' AND 'YYYYMM'
AND type = 'DeleteEvent'
AND repo.name = 'OWNER/REPO'
LIMIT 200
"

Доказательства для сбора:

  • События force-push (payload.size > 0, payload.distinct_size = 0)
  • DeleteEvents для веток/тегов
  • WorkflowRunEvents для подозрительной автоматизации CI/CD
  • PushEvents, предшествующие «разрыву» в git-логе (доказательство перезаписи)

Справочник: См. github-archive-guide.md для всех 12 типов событий и шаблонов запросов.


Исследователь 5: Исследователь обогащения IOC​

ГРАНИЦА РОЛИ: Вы обогащаете СУЩЕСТВУЮЩИЕ IOC из Фазы 1, используя ТОЛЬКО пассивные публичные источники. Не выполняйте никакой код из целевого репозитория.

Действия:

  • Для каждого SHA коммита: попытка восстановления через прямой URL GitHub (github.com/OWNER/REPO/commit/SHA.patch)
  • Для каждого домена/IP: проверка пассивного DNS, WHOIS-записей (через web_extract на публичных WHOIS-сервисах)
  • Для каждого имени пакета: проверка npm/PyPI на наличие соответствующих отчётов о вредоносных пакетах
  • Для каждого имени пользователя-актора: проверка профиля GitHub, истории контрибьюций, возраста учётной записи
  • Восстановление коммитов, сделанных через force-push, с использованием 3 методов (см. recovery-techniques.md)

Фаза 3: Консолидация доказательств​

После завершения работы всех исследователей:

  1. Запустите python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list, чтобы увидеть все собранные доказательства.
  2. Для каждого доказательства проверьте, что хеш content_sha256 соответствует исходному источнику.
  3. Сгруппируйте доказательства по:
    • Временной шкале: Отсортируйте все доказательства с временными метками в хронологическом порядке
    • Актору: Сгруппируйте по хендлу GitHub или email
    • IOC: Свяжите доказательства с соответствующим IOC
  4. Выявите расхождения: элементы, присутствующие в одном источнике, но отсутствующие в другом (ключевые индикаторы удаления).
  5. Пометьте доказательства как [VERIFIED] (подтверждено из 2+ независимых источников) или [UNVERIFIED] (только из одного источника).

Фаза 4: Формирование гипотез​

Гипотеза должна:

  • Формулировать конкретное утверждение (например, «Актор X сделал force-push в BRANCH в DATE, чтобы стереть коммит SHA»)
  • Ссылаться как минимум на 2 идентификатора доказательств, которые её поддерживают (EV-XXXX, EV-YYYY)
  • Определять, какие доказательства могли бы её опровергнуть
  • Быть помечена как [HYPOTHESIS] до валидации

Общие шаблоны гипотез (см. investigation-templates.md):

  • Компрометация мейнтейнера: легитимная учётная запись используется после захвата для внедрения вредоносного кода
  • Путаница зависимостей: сквоттинг имени пакета для перехвата установок
  • Инъекция CI/CD: вредоносные изменения workflow для запуска кода во время сборок
  • Тайпсквоттинг: почти идентичное имя пакета, нацеленное на допускающих опечатки
  • Утечка учётных данных: токен/ключ случайно закоммичен, а затем стёрт через force-push

Для каждой гипотезы запустите подагента delegate_task, чтобы попытаться найти опровергающие доказательства перед подтверждением.


Фаза 5: Валидация гипотез​

Подагент-валидатор ОБЯЗАН механически проверить:

  1. Для каждой гипотезы извлеките все указанные идентификаторы доказательств.
  2. Проверьте, что каждый ID существует в evidence.json (жёсткий сбой, если какой-либо ID отсутствует → гипотеза отклоняется как потенциально сфабрикованная).
  3. Проверьте, что каждое [VERIFIED] доказательство было подтверждено из 2+ источников.
  4. Проверьте логическую согласованность: поддерживает ли временная шкала, изображённая доказательствами, гипотезу?
  5. Проверьте альтернативные объяснения: может ли та же схема доказательств возникнуть из безобидной причины?

Результат:

  • VALIDATED: Все доказательства процитированы, проверены, логически согласованы, нет правдоподобного альтернативного объяснения.
  • INCONCLUSIVE: Доказательства поддерживают гипотезу, но существуют альтернативные объяснения или доказательств недостаточно.
  • REJECTED: Отсутствуют идентификаторы доказательств, непроверенные доказательства представлены как факт, обнаружена логическая несогласованность.

Отклонённые гипотезы возвращаются в Фазу 4 для доработки (макс. 3 итерации).


Фаза 6: Генерация финального отчёта​

Заполните investigation-report.md, используя шаблон из forensic-report.md.

Обязательные разделы:

  • Исполнительное резюме: вердикт в один абзац (Скомпрометирован / Чист / Неубедительно) с уровнем уверенности
  • Временная шкала: хронологическая реконструкция всех значимых событий с цитированием доказательств
  • Подтверждённые гипотезы: каждая со статусом и поддерживающими идентификаторами доказательств
  • Реестр доказательств: таблица всех записей EV-XXXX с источником, типом и статусом проверки
  • Список IOC: все извлечённые и обогащённые индикаторы компрометации
  • Цепочка хранения: как были собраны доказательства, из каких источников, в какие временные метки
  • Рекомендации: немедленные меры по смягчению последствий при обнаружении компрометации; рекомендации по мониторингу

Правила отчёта:

  • Каждое фактическое утверждение должно иметь как минимум одну ссылку [EV-XXXX]
  • Исполнительное резюме должно указывать уровень уверенности (Высокий / Средний / Низкий)
  • Все секреты/учётные данные должны быть отредактированы до [REDACTED]

Фаза 7: Завершение​

  1. Выполните финальный подсчёт доказательств: python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list
  2. Архивируйте полную директорию расследования.
  3. Если компрометация подтверждена:
    • Перечислите немедленные меры по смягчению (ротация учётных данных, закрепление хешей зависимостей, уведомление затронутых пользователей)
    • Определите затронутые версии/пакеты
    • Отметьте обязательства по раскрытию (если это публичный пакет: скоординируйтесь с реестром пакетов)
  4. Представьте финальный investigation-report.md пользователю.

Рекомендации по этичному использованию​

Этот навык предназначен для оборонительного расследования безопасности — защиты открытого программного обеспечения от атак на цепочки поставок. Его нельзя использовать для:

  • Преследования или сталкерства контрибьюторов или мейнтейнеров
  • Доксинга — корреляции активности на GitHub с реальными личностями в злонамеренных целях
  • Конкурентной разведки — расследования проприетарных или внутренних репозиториев без авторизации
  • Ложных обвинений — публикации результатов расследования без подтверждённых доказательств (см. защитные барьеры против галлюцинаций)

Расследования должны проводиться с принципом минимального вмешательства: собирайте только те доказательства, которые необходимы для подтверждения или опровержения гипотезы. При публикации результатов следуйте практике ответственного раскрытия информации и координируйте свои действия с затронутыми мейнтейнерами до публичного раскрытия.

Если расследование выявило реальную компрометацию, следуйте процессу скоординированного раскрытия уязвимостей:

  1. Сначала уведомите мейнтейнеров репозитория в частном порядке
  2. Дайте разумное время для исправления (обычно 90 дней)
  3. Скоординируйтесь с реестрами пакетов (npm, PyPI и т.д.), если затронуты опубликованные пакеты
  4. Подайте заявку на CVE, если это уместно

Лимиты API​

GitHub REST API устанавливает лимиты запросов, которые могут прервать крупные расследования, если ими не управлять.

Аутентифицированные запросы: 5 000/час (требуется переменная окружения GITHUB_TOKEN или аутентификация gh CLI) Неаутентифицированные запросы: 60/час (непригодны для расследований)

Рекомендации:

  • Всегда аутентифицируйтесь: export GITHUB_TOKEN=ghp_... или используйте gh CLI (аутентифицируется автоматически)
  • Используйте условные запросы (заголовки If-None-Match / If-Modified-Since), чтобы избежать расходования квоты на неизменённые данные
  • Для конечных точек с пагинацией загружайте все страницы последовательно — не распараллеливайте запросы к одной и той же конечной точке
  • Проверяйте заголовок X-RateLimit-Remaining; если он ниже 100, приостановите работу до временной метки X-RateLimit-Reset
  • BigQuery имеет свои собственные квоты (10 TiB/день на бесплатном уровне) — всегда сначала запускайте dry-run
  • CDX API Wayback Machine: формального лимита нет, но будьте вежливы (макс. 1-2 запроса/сек)

Если в середине расследования вы достигли лимита, запишите частичные результаты в хранилище доказательств и отметьте ограничение в отчёте.


Справочные материалы​

  • github-archive-guide.md — Запросы BigQuery, CDX API, 12 типов событий
  • evidence-types.md — Таксономия IOC, типы источников доказательств, типы наблюдений
  • recovery-techniques.md — Восстановление удалённых коммитов, PR, issues
  • investigation-templates.md — Готовые шаблоны гипотез по типу атаки
  • evidence-store.py — CLI-инструмент для управления JSON-хранилищем доказательств
  • forensic-report.md — Шаблон структурированного отчёта