
Автоматизированный уровень безопасности зависимостей для ИИ-помощников по кодированию, который проверяет пакеты на наличие CVE, typosquats, заброшенность, проблемы с возрастом версий и целостность хешей в экосистемах npm, PyPI, RubyGems, Maven, Go и Rust.
Когда ИИ-ассистенты программирования, такие как Claude, добавляют пакеты в ваш проект, они часто выбирают ту версию, которая звучит правильно, — не проверяя, есть ли у неё известные уязвимости, поддерживается ли пакет активно и не находится ли его имя в одном символе от вредоносной подделки.
safer-dependencies — это уровень безопасности для Claude Code: он находится между Claude и вашими файлами манифеста и автоматически выполняет проверки безопасности: установка уязвимых пакетов блокируется до её запуска, а рискованная версия, записанная в манифест, исправляется на диске сразу после записи. Он обнаруживает и исправляет рискованные зависимости — CVE, тайпсквоттинг, заброшенные пакеты и проблемы возраста версий, плюс период охлаждения для свежих релизов — в npm, PyPI, RubyGems, Maven, Go, Rust и PHP (Composer). Точный список того, что поддерживается, а что нет, см. в CAPABILITIES.md.
Впервые здесь? GETTING-STARTED.md проведёт вас от нуля до работающей установки примерно за пять минут.
Безопасность и конфиденциальность: см. SECURITY.md (раскрытие уязвимостей), PRIVACY.md (исходящие данные, без телеметрии) и CAPABILITIES.md (от чего инструмент защищает, а от чего — нет).
Лицензия (source-available — НЕ OSI «open source»): Вы можете свободно использовать и модифицировать его в своих целях, включая коммерческое использование внутри компании и создание продуктов, которые вы продаёте. Отдельная платная лицензия требуется только для монетизации самого программного обеспечения — его продажи, включения в продаваемый продукт или услугу или предоставления его функциональности третьим лицам за плату (включая размещение/SaaS/API). При распространении и создании производных работ необходимо сохранять лицензию и указывать авторство этого проекта. См. LICENSE (раздел 4 о коммерческом ограничении); запросы на коммерческую лицензию — через github.com/robert-auger.
GETTING-STARTED.md проведёт вас от нуля до работающей установки примерно за пять минут — предварительные требования, интерактивная установка и проверка. Полный справочник по установке (глобальная/проектная/ручная установка, особенности Windows, список разрешённых разрешений, обновление и удаление) см. в INSTALLATION.md.
Повседневное использование: после установки хуков ничего запускать не нужно — safer-dependencies работает автоматически в фоне. Когда Claude добавляет или устанавливает пакеты, он помечает рискованные зависимости и обновляет уязвимые версии до безопасной на месте — а также блокирует установку заведомо уязвимой версии до её запуска — так что небезопасные пакеты обнаруживаются и исправляются без вашего участия. Вы по-прежнему можете вызывать его напрямую в любой момент: «безопасен ли [email protected]?», «проверь настройку safer-dependencies» или «покажи статистику safer-dependencies».
Когда Claude собирается добавить пакет в ваш проект, safer-dependencies перехватывает действие и выполняет 5 проверок:
requirements.txt с привязками --hash=sha256:... объявленный хеш проверяется по опубликованным хешам PyPI; при несовпадении выдаётся WARNINGpaperclip, request, pycrypto, github.com/dgrijalva/jwt-go) сразу жёстко блокируются с предложением замены; пакеты без стабильного релиза за 2+ года получают предупреждение STALE:. Жёстко заблокированные пакеты удаляются из манифеста, и Claude спросит, как действовать дальше; пакеты только с пометкой stale остаются на месте.Если обнаружены проблемы, Claude выдаёт предупреждения и может откатиться к более безопасной версии. Все проверки записываются в ~/.claude/safer-dependencies-audit-YYYY-MM.log (один файл на календарный месяц).
Навык работает в пяти режимах (кратко ниже; самое глубокое обоснование дизайна находится в skills/safer-dependencies.md):
Когда Claude собирается записать import, добавить пакет в манифест или обновить lock-файл, навык запускается в вашей сессии:
Выбор версии выполняется автономными скриптами Python, поставляемыми с навыком, а не LLM, интерпретирующим правила. Команда выводит SELECTED: <version>, и Claude использует именно эту версию.
Настройте .claude/settings.json с хуком PostToolUse, чтобы включить автоматическую прозрачную проверку пакетов:
package.json) с изначально запрошенной версией — файл сохраняется на дискPostToolUse срабатывает сразу после завершения записи и вызывает safer-dependencies-shim.shUPDATED:, BLOCKED:, WARNING:, STALE:, MAJOR-UPDATE-CONFIRM:, REFACTOR-REQUIRED:, REGRESSION:, TYPOSQUAT-CONFIRM:, VERIFY:, ) через в stdout. предшествует , когда журнал аудита показывает, что тот же (файл, пакет) ранее уже был исправлен до той же безопасной цели — то есть субагент или устаревший план повторно внёс заведомо уязвимую версию, и оркестратор должен восстановить ранее одобренную версию, а не заново решать вопрос о мажорном обновлении.Примечание о дизайне — Shape C (коррекция после записи): хук НЕ блокирует запись. Каждая уязвимая версия сначала попадает на диск, а затем автоматически исправляется в том же цикле использования инструмента. Это осознанный выбор в сравнении с блокирующим дизайном PreToolUse — см. FAQ.md о компромиссах.
Пример сигнала:``` UPDATED: aiohttp 3.8.5 → 3.9.0 (HIGH: 33 CVEs fixed)
Родительский агент использует эти сигналы, чтобы выявить затронутый код и выполнить рефакторинг по мере необходимости.
### Pre-Install Mode (Bash Hook)
Настройте `.claude/settings.json` с хуком `PreToolUse:Bash`, чтобы включить
предварительную проверку команд установки менеджера пакетов. Это дополняет
(не заменяет) Intercept Mode — вместе они образуют многоуровневую защиту.
1. Claude выполняет вызов инструмента Bash (например, `npm install [email protected]`)
2. Хук `PreToolUse` срабатывает до выполнения вызова и запускает
`safer-dependencies-pretooluse-bash.sh`
3. Чистый bash-фильтр раннего этапа отсекает не-PM команды за ~115 мс
(без вызова Python), поэтому `git status` / `ls` / `npm test` несут
незначительные издержки на горячем пути
4. Для распознанных установок менеджера пакетов (`npm`/`pnpm`/`yarn`
`install`/`i`/`add`) помощник токенизирует через `shlex`, извлекает каждый
аргумент `pkg@version` и отправляет POST в OSV
5. Любой уязвимый конкретный пин → хук возвращает
`permissionDecision: "deny"` с GHSA-id + CVSS +
сводкой для каждой находки, а также подсказку вызвать навык safer-dependencies
6. Установка никогда не выполняется — ни сетевого запроса, ни postinstall-скриптов
**Почему это существует в дополнение к Intercept Mode:** пост-записывающий шим
слеп к Bash. `npm install [email protected]` выполняется до конца (и
postinstall-скрипты выполняются) до того, как сработает аудит; `npm install -g
typosquat-pkg` вообще не записывает манифест проекта. Pre-Install Mode
структурно закрывает эти пробелы.
Pre-Install Mode видит только то, что пользователь **ввёл** (аргументы `pkg@version` в
командной строке). Он не видит транзитивное дерево, которое резолвер
фактически установит. **Post-Install Mode** (ниже) проверяет lockfile после того, как
установка завершится, — два режима дополняют друг друга, а не дублируют.
**Область применения:** рассматриваемые здесь CLI менеджеров пакетов охватывают пять экосистем
(npm/pnpm/yarn/bun/npx/deno, pip/pip3/pipx/pipenv/uv/uvx/poetry, gem/bundle,
go, cargo), плюс Maven через Intercept Mode (зависимости Maven обычно
объявляются в `pom.xml`/`build.gradle`, а не добавляются через глагол CLI).
> **Известный пробел:** CLI Maven поддерживает прямую загрузку через
> `mvn dependency:get -Dartifact=group:art:version` и `mvn dependency:copy`.
> Этот хук пока не распознаёт такие вызовы. Если вы используете их
> регулярно, существующий пост-записывающий шим по-прежнему перехватывает всё, что попадает в
> ваш манифест, но защита до загрузки применяется только к
> перечисленным выше экосистемам. Отслеживается как последующая задача.
Распознаваемый синтаксис по экосистемам:
| PM | Глаголы | Синтаксис закрепления конкретной версии |
|---|---|---|
| `npm`, `pnpm`, `yarn`, `bun` | `install`, `i`, `add` (плюс `yarn`/`pnpm dlx`, `bun x`, `yarn create`) | `[email protected]`, `@scope/[email protected]` |
| `npx` | (без глагола — пакет указывается первой позицией) | `[email protected]` |
| `deno` | `add`, `install` | `npm:[email protected]` (спецификации с префиксом npm) |
| `pip`, `pip3`, `pipx`, `pipenv`, `uv`, `uvx`, `poetry` | `install` (pip/pip3/pipx/pipenv) / `add` (uv/poetry) / без глагола (uvx) | `pkg==1.2.3` (дополнительные зависимости `pkg[extra]==X` также обрабатываются) |
| `gem`, `bundle` | `install` (gem) / `add` | `-v 1.2.3`, `--version 1.2.3`, `--version=1.2.3` (отдельный флаг) |
| `go` | `get`, `install` | `[email protected]` (должен включать префикс `v` согласно модулям Go) |
| `cargo` | `add`, `install` | `[email protected]` |
Диапазонные закрепления (npm `^4.17`, pip `>=`, poetry `^`/`~`, Go `@latest`) и
неуказанные версии передаются в Intercept Mode после установки —
пост-записывающий шим проверяет всё, что выберет резолвер. Авто-перезапись на
безопасную версию запланирована как последующая задача.
**Режим отказа:** fail-open. Любая ошибка (отсутствие Python, сбой сети,
некорректный ввод) завершается кодом 0 без вывода, позволяя bash продолжить.
Intercept Mode по-прежнему выполняется после установки, поэтому неудачная предварительная проверка
без сбоев переходит к существующей защите.
**Пример запрета:**```
safer-dependencies pre-flight audit blocked this install.
Vulnerable pinned version(s) detected:
- [email protected] → GHSA-35jh-r3h4-6jhm (CVSS:7.4): Command Injection in lodash
Re-run with a patched version, or invoke the safer-dependencies skill
for a recommended pin.
Настройте .claude/settings.json с хуком PostToolUse:Bash, чтобы включить аудит после выполнения команд Bash. Он запускает три независимых сканирования в cwd команды, каждое из которых закрывает пробел, который другие хуки не могут закрыть:
npm install, bundle install, poetry install, uv sync, go mod tidy и т.д.) проверяет недавно изменённые lock-файлы (package-lock.json, Gemfile.lock, poetry.lock, uv.lock, go.sum, yarn.lock, pnpm-lock.yaml, Pipfile.lock). Это закрывает пробел транзитивных CVE, который Pre-Install не видит: пользователь ввёл pkg@version, но резолвер мог подтянуть десятки транзитивных зависимостей, которые никто не называл.Как выполняется сканирование:
PostToolUse срабатывает после завершения команды и вызывает safer-dependencies-posttooluse-bash.shls / git / cat несут незначительные издержкиcwd с помощью find -maxdepth 5 (покрывает структуры монорепозиториев; исключает node_modules, .git, .venv, venv) в поисках файлов, изменённых за последние 60 секунд — переопределяется через SAFE_DEP_POSTINSTALL_MTIME_WINDOWЧто это ловит, а Pre-Install — нет: транзитивные уязвимости. Безобидный на вид bundle install может подтянуть [email protected] (CVE-2025-27610) как транзитивную зависимость от sinatra — пользователь никогда не вводил rack, поэтому Pre-Install не видит её, но Post-Install читает разрешённый Gemfile.lock и сообщает о CVE.
Область действия: Scan A не переписывает разрешённые версии — контракт автокоррекции применяется только к манифестам, которые Claude написал напрямую. Для транзитивных CVE исправление обычно заключается в том, чтобы «обновить прямую зависимость, которая владеет транзитивной», а это требует человеческой оценки. Scan B выполняет автокоррекцию, потому что проверяет манифесты через тот же путь к шиму, что и Intercept Mode. Scan A пропускается, когда уровень проверки transitive установлен в off (config set checks.transitive off).
Режим сбоя: fail-open, как и у других хуков. Любая ошибка (отсутствующий шим, повреждённый payload, недоступный Python) приводит к молчаливому выходу с кодом 0.
Пример предупреждения:``` WARNING: [email protected] in lock file has GHSA-29mw-wpgm-hmr9, GHSA-35jh-r3h4-6jhm
### Режим Post-Agent (пара хуков Agent)
Четыре описанных выше режима срабатывают только для вызовов инструментов из **root-сессии**. Когда корневая сессия отправляет субагента (через инструмент `Agent` — многие навыки и слэш-команды делают это внутренне), вызовы Write/Edit/Bash субагента обходят все эти режимы. Режим Post-Agent — это реактивная страховочная сеть для этого пробела.
1. Хук `PreToolUse:Agent` (`safer-dependencies-pretooluse-agent.sh`) запускается непосредственно перед каждой отправкой агента и создаёт файл-маркер по пути `/tmp/.safer-deps-agent-<PPID>-<session_id>.sentinel` (если идентификатор сессии недоступен, используется имя только с PPID)
2. Субагент выполняется и может записывать манифесты или lock-файлы
3. Хук `PostToolUse:Agent` (`safer-dependencies-posttooluse-agent.sh`) запускается после возврата вызова Agent, находит с помощью `find` все манифесты и lock-файлы новее маркера и проверяет каждый из них через тот же путь шима
4. Результаты появляются как `additionalContext` в следующем ходе корневой сессии; маркер удаляется
Вложенные субагенты покрываются автоматически — `PostToolUse:Agent` корневой сессии срабатывает только после того, как вся работа внешнего агента (включая всё, что *он* отправлял) уже сохранена на диск. Единственный пробел — глобальная установка, которая не записывает ни манифест, ни lock-файл (`npm install -g …`): сканировать нечего. Как и остальные хуки, он работает по принципу fail-open — любая ошибка (отсутствующий маркер, отсутствующий шим, нечитаемые данные) молча завершается с кодом 0. Полное обоснование дизайна находится в `skills/safer-dependencies.md`.
## Что вызывает срабатывание
Навык срабатывает автоматически, когда Claude:
**Операции с манифестами и установка**
- Добавляет или обновляет пакет в `package.json`, `requirements.txt`, `Gemfile`, `pom.xml`, `build.gradle`, `Cargo.toml`, `go.mod` или любом другом поддерживаемом манифесте
- Пишет `import`, `require` или `use` для пакета, ещё не объявленного в манифесте
- Создаёт или обновляет lock-файл (проверяются только новые/изменённые записи)
- Запускает установку через пакетный менеджер через Bash (`npm install`, `bundle install`, `poetry install`, `uv sync`, `go mod tidy` и т. д.) — Pre-Install проверяет аргументы команды, Post-Install проверяет полученный lock-файл
- Пишет `Dockerfile` или CI workflow (`.github/workflows/*.yml` и т. д.), содержащий закреплённые шаги установки через пакетный менеджер
**Вопросы о выборе и рекомендациях**
- Сравнение библиотек/фреймворков: «стоит ли использовать axios или node-fetch?», «moment или dayjs?», «что лучше, X или Y?»
- Запросы рекомендаций: «какой хороший HTTP-клиент для Python?», «посоветуй библиотеку для логирования в Go», «какой пакет работает с CSV в Node?»
- Выбор версии: «какую версию Django мне использовать?», «последний стабильный Flask?»
**Выражения намерения использовать (до добавления)**
- «Я хочу использовать FastAPI для этого», «думаю добавить Celery», «мы рассматриваем Prisma как ORM», «давай используем Tailwind»
**Вопросы о состоянии и доверии к пакетам**
- «moment.js всё ещё поддерживается?», «этот gem ещё активен?», «X заброшен?», «X достиг конца жизни (EOL)?», «можно ли доверять этому пакету?», «когда faker обновлялся в последний раз?»
**Команды создания каркаса проекта**
- `npx create-react-app`, `npm create vite@latest`, `django-admin startproject`, `rails new`, `cargo new` + `cargo add`, «создать новый проект FastAPI с нуля»
**Неявные добавления пакетов (запросы возможностей, подразумевающие новую зависимость)**
- «Добавь кэширование Redis в приложение», «подключись к Postgres», «добавь JWT-аутентификацию», «напиши код для отправки email» — срабатывает, когда в манифесте ещё нет пакета для этой возможности
**Миграция и перенос**
- «Мигрируй с requests на httpx», «перейди с CRA на Vite», «перенеси с moment на date-fns» — проводит аудит нового пакета
Он **не** срабатывает для:
- Импортов из стандартной библиотеки (`os`, `fs`, `java.util.*` и т. д.)
- Уже объявленных зависимостей, которые не изменяются
- Академического обсуждения внутреннего устройства пакета («объясни, как работает React reconciler», «как работает модульное разрешение webpack?») — вопросы сравнения и выбора по-прежнему срабатывают
- Установки приложений уровня ОС, сред выполнения или расширений IDE (сам Python, Docker, Homebrew, расширения VS Code)
## Что в этом репозитории
Это **набор из навыка и хуков**, а не один файл навыка. Полная установка разворачивает следующие компоненты:
| Файл | Роль |
|---|---|
| `skills/safer-dependencies.md` | **Навык** (`SKILL.md` после установки). Описывает процедуры аудита и включает режим управления для установки/статистики. |
| `skills/safer-dependencies-shim.sh` | Хук `PostToolUse:Write`/`Edit` — проверяет записи манифестов и lock-файлов и автоматически исправляет уязвимые версии на месте (режим Intercept). |
| `skills/safer-dependencies-pretooluse-bash.sh` | Хук `PreToolUse:Bash` — предварительный OSV-аудит команд установки пакетных менеджеров; отклоняет уязвимые конкретные закреплённые версии до запуска установки (режим Pre-Install). |
| `skills/safer-dependencies-posttooluse-bash.sh` | Хук `PostToolUse:Bash` — последующий аудит после Bash-команд; ловит транзитивные CVE в только что созданных lock-файлах, манифестах, изменённых через `sed`/`jq`/скрипты, и в разрешённом окружении обычного `pip install` (режим Post-Install). |
| `skills/safer-dependencies-pretooluse-agent.sh` + `skills/safer-dependencies-posttooluse-agent.sh` | Пара хуков `PreToolUse:Agent` + `PostToolUse:Agent` — закрывает пробел покрытия субагентов. Режимы 2–4 срабатывают только для вызовов инструментов root-сессии, поэтому любой манифест, записанный субагентом, обходит их. Post-Agent проверяет всё, что субагент записал после каждого возврата вызова инструмента Agent (режим Post-Agent). |
| `skills/scripts/` | Общая Python-библиотека (`safedep/`) и автономные скрипты-резолверы, используемые всеми хуками. |
| `skills/scripts/safer_dependencies_manager.py` | Модуль управления для интерактивной установки, статистики использования и проверки настройки. |
Одного файла навыка недостаточно — без хуков автоматический вызов зависит от того, решит ли Claude обратиться к навыку. Установите все пять компонентов для полного покрытия; многие навыки и слэш-команды внутренне запускают субагентов, поэтому пара Post-Agent важна, даже если вы никогда явно не создаёте их. (См. [FAQ.md](https://github.com/robert-auger/safer-dependencies/blob/HEAD/FAQ.md#why-a-skill-alone-is-not-sufficient) — почему сам по себе навык не может гарантировать покрытие.)
## Поддерживаемые экосистемы
| Экосистема | Манифест | Lock-файл |
|-----------|----------|-----------|
| npm | `package.json` | `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` |
| PyPI | `requirements.txt`, `pyproject.toml`, `Pipfile`, `setup.py`, `setup.cfg` | `Pipfile.lock`, `poetry.lock`, `uv.lock` |
| RubyGems | `Gemfile`, `*.gemspec` | `Gemfile.lock` |
| Maven | `pom.xml`, `build.gradle`, `libs.versions.toml` | -- |
| Go | `go.mod` | `go.sum` |
| Rust | `Cargo.toml` | `Cargo.lock` |
| PHP (Composer) | `composer.json` | `composer.lock` |
## Установка
Новичок в проекте? Начните с **[GETTING-STARTED.md](https://github.com/robert-auger/safer-dependencies/blob/HEAD/GETTING-STARTED.md)**. Краткая версия:```bash
git clone https://github.com/robert-auger/safer-dependencies /tmp/safer-dependencies
python3 /tmp/safer-dependencies/skills/scripts/safer_dependencies_manager.py interactive_install
Установщик запрашивает область действия (глобальную или для проекта) и то, какие хуки включить, а затем сам записывает settings.json — как записи хуков, так и список разрешений, который позволяет проверочным командам навыка выполняться без запроса одобрения при каждом аудите.
Всё остальное, связанное с установкой, описано в INSTALLATION.md — единственном справочнике по механике установки: установка вручную файл за файлом (глобальная и на уровне проекта), особенности Windows, Post-Agent хуки, список разрешений, проверка настройки, обновление, закрепление за тегом релиза и удаление.
После установки повседневное управление осуществляется через естественный язык в Claude — install safer-dependencies (повторный запуск / изменение хуков), show safer-dependencies stats, check safer-dependencies setup — или через меню /safer-dependencies. Обновление также выполняется прямо в сессии: /safer-dependencies update применяет последний релиз (update --check для пробного запуска, update --rollback для отката); модель доверия описана в INSTALLATION.md.
Примечание о платформах: поддерживаются macOS, Linux и Windows. Для Windows требуются Git for Windows (предоставляет bash) и Python 3 в
PATH— WSL не нужен. Практическое тестирование на сегодняшний день сосредоточено на macOS и Windows; поддержка Linux проверяется автоматической CI-матрицей.
После установки можно настроить две вещи:
npm audit / bundle audit в точной форме и собственные скрипты-резолверы навыка), чтобы аудиты выполнялись без запроса одобрения каждый раз; curl никогда не получает предварительного одобрения, а npm view / pip-audit включаются по желанию через профиль Convenience. Интерактивный установщик сам записывает основные записи; при ручной установке полный блок добавляется вручную. Полный блок и обоснование: INSTALLATION.md → Список разрешений.off/warn/block для каждой проверки любого типа, редактируется с помощью /safer-dependencies config и хранится в ~/.config/safer-dependencies/config.toml. Схема и семантика уровней: .Каждая проверка записывается в ~/.claude/safer-dependencies-audit-YYYY-MM.log (один файл на календарный месяц, где YYYY-MM — год и месяц в UTC) одной JSON-строкой. Полный путь можно переопределить переменной окружения SAFE_DEP_AUDIT_LOG (если она задана, суффикс с датой не добавляется). Файлы также ротируются по размеру, когда превышают SAFE_DEP_LOG_MAX_BYTES (по умолчанию 10 МиБ; значение 0 отключает ротацию). Задайте SAFE_DEP_MODEL, чтобы переопределить значение модели, записываемое в source.model в каждой записи — удобно для A/B-сравнения версий моделей.
Все пять режимов добавляют записи в один и тот же файл. Каждая запись содержит блок source (схема 2.2), указывающий, какой компонент её создал:
source.model фиксирует модель Claude Code, активную в сессии (например, "claude-sonnet-4-6"). Поле присутствует в схеме 2.1+; записи, созданные более старыми установками, не содержат этого поля. Команда stats при отсутствии поля корректно переходит на значение "unknown".
Фильтрация по source.component с помощью jq:```bash
jq -r '.source.component' audit.log | sort | uniq -c | sort -rn
jq -c 'select(.source.component == "bash.pretooluse")' audit.log
jq -c 'select(.source.mode == "fail_open") | {component: .source.component, reason: .fail_open.reason, ts}' audit.log
Для более лёгкого анализа попросите Claude предоставить статистику использования вместо ручного разбора логов:```
"Show safer-dependencies stats for the last month"
Это обеспечивает удобочитаемые сводки активности, влияния на безопасность и показателей производительности, извлечённые из этих журналов аудита.
Формы записей (схема 2.2). Три различные формы используют один и тот же заголовок ts / schema / source:
Записи аудита: Intercept Mode выполняет полный конвейер (происхождение, возраст версии, OSV, abandoned/stale, typosquat, подписи), поэтому все массивы могут заполняться. Pre-Install Mode сегодня выполняет только OSV, поэтому abandoned / stale / typosquat / signatures всегда пусты. Диспетчеризация Post-Install (аудит lockfile) записывает данные под shim.posttooluse, при этом findings заполняется строками WARNING: от аудиторов lockfile. Массив notes содержит информационные сигналы NOTE: (например, манифест пропущен, так как не закреплён).
Схема 2.2 добавила — аддитивно — четыре поля в lockfile записи аудита: lockfile, manifest_ref, relation_summary (классификация direct/transitive/unknown для каждого помеченного пакета относительно sibling-манифеста) и блок policy, фиксирующий действующий уровень transitive. Обновление обратно совместимо: читатели записей 2.1 допускают новые поля, а поле source.model остаётся присутствующим начиная с 2.1.```json
{
"ts": "2026-04-19T12:34:56Z",
"schema": "2.2",
"source": {
"component": "shim.posttooluse",
"script": "shim.sh",
"hook": "PostToolUse:Write",
"tool": "Write",
"mode": "intercept",
"model": "claude-sonnet-4-6"
},
"file": "/path/to/project/package.json",
"ecosystem": "npm",
"checked": ["[email protected]", "[email protected]"],
"findings": ["UPDATED: express 4.18.2 → 4.22.1 (HIGH: 1 CVE fixed)"],
"abandoned": [],
"stale": [],
"typosquat": [],
"unknown": [],
"signatures": [],
"notes": [],
"clean": ["[email protected]"]
}
Пример режима предустановки (Bash-хук, уязвимый PIN отклонён):```json
{
"ts": "2026-04-23T06:56:21Z",
"schema": "2.2",
"source": {
"component": "bash.pretooluse",
"script": "pretooluse-bash.sh",
"hook": "PreToolUse:Bash",
"tool": "Bash",
"mode": "intercept",
"model": "claude-sonnet-4-6"
},
"file": "bash:npm install [email protected] [email protected]",
"ecosystem": "npm",
"checked": ["[email protected]", "[email protected]"],
"findings": [
"BLOCKED: [email protected] GHSA-35jh-r3h4-6jhm (CVSS:3.1/...): Command Injection in lodash"
],
"abandoned": [],
"stale": [],
"typosquat": [],
"unknown": [],
"signatures": [],
"notes": [],
"clean": ["[email protected]"]
}
Пример режима Fail-open (Post-Install Bash hook вызывается без соседнего shim — сломанная установка):```json { "ts": "2026-05-03T07:14:11Z", "schema": "2.2", "source": { "component": "bash.posttooluse", "script": "safer-dependencies-posttooluse-bash.sh", "hook": "PostToolUse", "tool": "Bash", "mode": "fail_open", "model": "claude-sonnet-4-6" }, "fail_open": { "reason": "shim_missing", "detail": "/home/alice/.claude/skills/safer-dependencies" } }
Запись с режимом fail-open означает: «этот хук сработал, но завершился досрочно без аудита, потому что отсутствовало нечто обязательное». Используйте указанный выше фильтр jq (`select(.source.mode == "fail_open")`), чтобы выявить каждое тихое событие потери защиты в вашем журнале.
Когда шим запускается в режиме пробного прогона (`SAFE_DEP_DRY_RUN=1`), записи также содержат `"mode": "dry_run"`, чтобы последующий анализ мог отфильтровать вызовы только для аудита.
## Требования
- Python 3.9+ (хуки проверяют его наличие и на более старых интерпретаторах работают в режиме fail-open)
- `curl` (для вызовов registry API и проверок уязвимостей OSV)
- Инструменты экосистем (необязательно; при их отсутствии навык переключается на OSV API):
- `npm` для пакетов npm
- `pip-audit` для пакетов Python
- `bundle` для пакетов Ruby
- `dependency-check` для пакетов Java
## FAQ
Обоснование проектных решений (почему `PostToolUse` вместо `PreToolUse`, почему подписи не проверяются, почему скрипты и шим дублируются, особенности загрузки навыков и т. д.) документировано в [`FAQ.md`](https://github.com/robert-auger/safer-dependencies/blob/HEAD/FAQ.md).
CLEAN:hookSpecificOutput.additionalContextREGRESSION:MAJOR-UPDATE-CONFIRM:ls, cat, git status, …), проверяет недавно изменённые манифесты. Это единственный запасной механизм для правок манифестов, сделанных через sed -i, jq или скрипт, — они обходят инструмент Write/Edit, на который опирается режим Intercept Mode.pip install / pip install -r requirements.txt не создаёт lock-файл, поэтому Scan A никогда не видит разрешённое дерево зависимостей. После установки через pip Scan C повторно вызывает тот же pip с read-only-опцией list --format=json и проверяет через OSV всё разрешённое окружение (прямые + транзитивные зависимости).PostToolUse:WritehookSpecificOutputskills/references/configuration.md| Уровень | Значение | Пример |
|---|
| CRITICAL | Остановиться и спросить пользователя | Обнаружен typosquatting, изменённая подпись |
| HIGH | Предупредить и продолжить | Известная CVE, пакет младше 30 дней |
| MEDIUM | Предупредить и продолжить | Версия младше 7 дней, отсутствует подпись |
| LOW | Предупредить и продолжить | Неподписанный Ruby gem (ожидаемо) |
source.component | Кем создан | Триггер |
|---|
shim.posttooluse | shim.sh | Запись манифеста или lock-файла (Intercept Mode, диспетчеризация Post-Install) |
shim.install_error | shim.sh | Сбой предварительной проверки установки шима |
bash.pretooluse | pretooluse-bash.sh | Bash-команда установки (Pre-Install Mode) |
bash.posttooluse | posttooluse-bash.sh | Сам Post-Install Bash-хук, когда он переходит в режим fail-open, не достигнув шима |
agent.pretooluse | pretooluse-agent.sh | Зарезервировано для Pre-Agent fail-open событий (сам хук в настоящее время не выводит ничего при успехе) |
agent.posttooluse | posttooluse-agent.sh | Post-Agent fail-open события хука (например, shim missing, python_missing) |
manual.skill | Claude, работающий в Normal Mode | Ручной аудит, вызванный инлайн |
| Форма | Когда записывается | Отличительные поля |
|---|
| Запись аудита | Аудит манифеста / lockfile / bash-install | file, ecosystem, checked, findings, abandoned, stale, typosquat, unknown, signatures, notes, clean |
| Запись об ошибке установки | Ошибка установки при предварительной проверке shim (компонент shim.install_error) | install_error, shim_dir, scripts_dir |
| Запись fail-open | Любая точка входа хука завершается досрочно из-за helper_missing / shim_missing / python_missing. source.mode равен "fail_open" | fail_open: { reason, detail? } |