
Camada automatizada de segurança de dependências para assistentes de codificação de IA que audita pacotes em busca de CVEs, typosquats, abandono, problemas de idade de versão e integridade de hash nos ecossistemas npm, PyPI, RubyGems, Maven, Go e Rust.
Quando assistentes de codificação com IA, como o Claude, adicionam pacotes ao seu projeto, eles frequentemente escolhem qualquer versão que pareça adequada — sem verificar se ela possui vulnerabilidades de segurança conhecidas, se o pacote ainda é mantido ativamente ou se o nome está a um erro de digitação de um imitador malicioso.
safer-dependencies é uma camada de segurança para o Claude Code: ela fica entre o Claude e seus arquivos de manifesto e executa suas verificações de segurança automaticamente: instalações vulneráveis são negadas antes de serem executadas, e uma versão arriscada escrita em um manifesto é corrigida no disco logo após a escrita. Ela detecta e corrige dependências arriscadas — CVEs, typosquats, pacotes abandonados e problemas de idade de versão, além de um período de espera para lançamentos totalmente novos — em npm, PyPI, RubyGems, Maven, Go, Rust e PHP (Composer). Consulte CAPABILITIES.md para saber exatamente o que é e o que não é coberto.
Novo aqui? GETTING-STARTED.md leva você do zero a uma instalação funcional em cerca de cinco minutos.
Segurança e privacidade: consulte SECURITY.md (divulgação de vulnerabilidades), PRIVACY.md (saída de dados, sem telemetria) e CAPABILITIES.md (o que a ferramenta defende e o que não defende).
Licença (código-fonte disponível — NÃO é "código aberto" OSI): Livre para usar e modificar para seus próprios fins, incluindo uso interno com fins lucrativos/empresarial e construção de produtos que você vende. Uma licença paga separada é necessária para monetizar o software — vendê-lo, distribuí-lo dentro de um produto ou serviço que é vendido, ou oferecer sua funcionalidade a terceiros mediante taxa (incluindo hospedado/SaaS/API). Redistribuição e derivados devem manter a licença e creditar este projeto. Consulte (Seção 4 para a restrição comercial); solicitações de licença comercial via .
GETTING-STARTED.md leva você do zero a uma instalação funcional em cerca de cinco minutos — pré-requisitos, a instalação interativa e a verificação. Para a referência completa de instalação (instalações globais/projeto/manuais, especificidades do Windows, a lista de permissões, atualização e desinstalação), consulte INSTALLATION.md.
Uso diário: uma vez que os hooks estão instalados, não há nada para executar — safer-dependencies funciona automaticamente em segundo plano. À medida que o Claude adiciona ou instala pacotes, ele sinaliza dependências arriscadas e atualiza versões vulneráveis para uma versão segura no local — e bloqueia uma instalação conhecidamente vulnerável antes mesmo de ela ser executada — para que pacotes inseguros sejam detectados e corrigidos sem que você precise pedir. Você ainda pode invocá-lo diretamente a qualquer momento: "[email protected] é seguro?", "verifique a configuração do safer-dependencies" ou "mostre estatísticas do safer-dependencies".
Quando o Claude está prestes a adicionar um pacote ao seu projeto, o safer-dependencies intercepta e executa 5 verificações:
requirements.txt do PyPI com pins --hash=sha256:..., o hash declarado é validado contra os hashes publicados do PyPI; uma incompatibilidade emite um AVISOpaperclip, request, pycrypto, github.com/dgrijalva/jwt-go) são bloqueados imediatamente com uma substituição sugerida; pacotes sem lançamento estável em 2+ anos recebem um aviso consultivo STALE:. Pacotes bloqueados são removidos do manifesto e o Claude perguntará como proceder; pacotes apenas desatualizados são mantidos no local.Se problemas forem encontrados, o Claude emite avisos e pode recuar para uma versão mais segura. Todas as verificações são registradas em ~/.claude/safer-dependencies-audit-YYYY-MM.log (um arquivo por mês calendário).
A skill é acionada automaticamente quando o Claude:
Operações de manifesto / instalação
package.json, requirements.txt, Gemfile, pom.xml, build.gradle, Cargo.toml, go.mod ou qualquer outro manifesto suportadoimport, require ou use para um pacote ainda não declarado no manifestonpm install, bundle install, poetry install, uv sync, go mod tidy, etc.) — Pré-Instalação audita os argumentos do comando, Pós-Instalação audita o arquivo de bloqueio resultanteDockerfile ou fluxo de trabalho de CI (.github/workflows/*.yml, etc.) que incorpora etapas de instalação fixadas do gerenciador de pacotesPerguntas de seleção e recomendação
Expressões de intenção de uso (pré-adição)
Perguntas sobre saúde e confiança de pacotes
Comandos de scaffolding
npx create-react-app, npm create vite@latest, django-admin startproject, rails new, cargo new + cargo add, "inicializar um novo projeto FastAPI"Adições implícitas de pacotes (solicitações de recursos que implicam uma nova dependência)
Migração e portabilidade
Ele não dispara para:
os, fs, java.util.*, etc.)Este é um pacote de skill + hooks, não um único arquivo de skill. Uma instalação completa implanta estas peças:
| Arquivo | Função |
|---|---|
skills/safer-dependencies.md | A skill (SKILL.md após a instalação). Descreve procedimentos de auditoria e inclui modo de gerenciamento para instalação/estatísticas. |
skills/safer-dependencies-shim.sh | Hook PostToolUse:Write/Edit — audita gravações de manifesto e arquivo de bloqueio e corrige automaticamente versões vulneráveis no local (Modo de Interceptação). |
skills/safer-dependencies-pretooluse-bash.sh | Hook PreToolUse:Bash — auditoria OSV pré-voo de comandos de instalação do gerenciador de pacotes; nega pins concretos vulneráveis antes de a instalação ser executada (Modo Pré-Instalação). |
skills/safer-dependencies-posttooluse-bash.sh | Hook PostToolUse:Bash — auditoria pós-voo após comandos Bash; captura CVEs transitivos em arquivos de bloqueio recém-escritos, manifestos editados via sed/jq/scripts e o ambiente resolvido de pip install simples (Modo Pós-Instalação). |
skills/safer-dependencies-pretooluse-agent.sh + skills/safer-dependencies-posttooluse-agent.sh | Par de hooks PreToolUse:Agent + PostToolUse:Agent — fecha a lacuna de cobertura de subagentes. Os Modos 2–4 só disparam para chamadas de ferramentas da sessão raiz, portanto qualquer manifesto que um subagente escreva os ignora. Pós-Agente audita o que o subagente escreveu após cada chamada de ferramenta Agent retornar (Modo Pós-Agente). |
skills/scripts/ | Biblioteca Python compartilhada (safedep/) e scripts de resolução independentes usados por todos os hooks. |
skills/scripts/safer_dependencies_manager.py | Módulo de gerenciamento para instalação interativa, estatísticas de uso e validação de configuração. |
Apenas o arquivo de skill não é suficiente — sem hooks, a invocação automática depende de o Claude decidir alcançar a skill. Instale todas as cinco peças para cobertura completa; muitas skills e comandos de barra despacham subagentes internamente, então o par Pós-Agente importa mesmo se você nunca gerar um explicitamente. (Consulte FAQ.md para saber por que uma skill sozinha não pode garantir cobertura.)
| Ecossistema | Manifesto | Arquivo de bloqueio |
|---|---|---|
| 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 |
Novo no projeto? Comece com GETTING-STARTED.md. A versão resumida:```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
O instalador solicita o escopo (global vs projeto) e quais hooks habilitar, depois grava o `settings.json` para você — tanto as entradas de hooks **quanto** a lista de permissões que permite que os comandos de verificação da skill sejam executados sem um prompt de aprovação a cada auditoria.
Todo o resto relacionado à instalação está em **[INSTALLATION.md](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md)**, a referência única para a mecânica de instalação: instalações manuais arquivo por arquivo (global e em nível de projeto), especificidades do Windows, hooks do Post-Agent, a [lista de permissões](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#permissions-allowlist), verificação da configuração, atualização, fixação em uma tag de release e desinstalação.
Após a instalação, o gerenciamento do dia a dia funciona por linguagem natural com o Claude — `install safer-dependencies` (re-executar / alterar hooks), `show safer-dependencies stats`, `check safer-dependencies setup` — ou pelo menu `/safer-dependencies`. A atualização também acontece na sessão: `/safer-dependencies update` aplica o release mais recente (`update --check` para uma simulação, `update --rollback` para desfazer); veja [INSTALLATION.md](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#in-session-self-updater-safer-dependencies-update) para o modelo de confiança.
> **Nota sobre plataformas:** macOS, Linux e Windows são suportados. O Windows precisa do Git for Windows (que fornece o bash) e do Python 3 no `PATH` — sem necessidade de WSL. Os testes práticos até o momento focaram em **macOS e Windows**; o suporte a Linux é exercitado pela matriz de CI automatizada.
### Configuração
Duas coisas são configuráveis após a instalação:
- **Lista de permissões** — pré-aprova os comandos de verificação somente leitura da skill (as regras de forma exata do `npm audit` / `bundle audit` e os scripts de resolução da própria skill) para que as auditorias sejam executadas sem um prompt de aprovação a cada vez; `curl` nunca é pré-aprovado, e `npm view` / `pip-audit` são opcionais por meio do perfil Convenience. O instalador interativo grava as entradas principais para você; instalações manuais adicionam o bloco completo à mão. Bloco completo e justificativa: [INSTALLATION.md → Lista de permissões](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#permissions-allowlist).
- **Política de segurança** — a janela/modo de espera da idade do release e um nível `off`/`warn`/`block` por verificação para cada tipo de verificação, editados com `/safer-dependencies config` e armazenados em `~/.config/safer-dependencies/config.toml`. Esquema e semântica dos níveis: [`skills/references/configuration.md`](https://github.com/robert-auger/safer-dependencies/blob/main/skills/references/configuration.md).
### Alterando o período de espera
O período de espera (chamado de **cooloff** na configuração) é a idade mínima que um release deve atingir antes que a skill o selecione — padrão de **7 dias**. Para alterá-lo, peça ao Claude ou execute o comando de configuração diretamente:```
/safer-dependencies config set cooloff.days 14 # require releases to be 14+ days old
/safer-dependencies config set cooloff.mode block # gate strength: off | warn | block (default: warn)
/safer-dependencies config unset cooloff.days # revert to the 7-day default
/safer-dependencies config # show effective values and where each comes from
As mesmas ações funcionam fora de uma sessão do Claude:```bash python3 skills/scripts/safer_dependencies_manager.py config set cooloff.days 14
A configuração persiste em `~/.config/safer-dependencies/config.toml` (na seção `[cooloff]`); as variáveis de ambiente `SAFE_DEP_COOLOFF_DAYS` e `SAFE_DEP_COOLOFF_MODE` substituem o arquivo por sessão. Três comportamentos a conhecer: `mode = "off"` remove completamente o filtro de idade da seleção de versões; uma reescrita orientada por CVE ignora a barreira, de modo que uma correção de segurança nunca é retida por ser demasiado recente; e a barreira cobre npm, PyPI, RubyGems e crates.io — Maven e Go são intencionalmente não abrangidos. Semântica completa: [`skills/references/configuration.md`](https://github.com/robert-auger/safer-dependencies/blob/main/skills/references/configuration.md).
## Níveis de aviso
| Nível | Significado | Exemplo |
|-------|---------|---------|
| CRITICAL | Parar e perguntar ao utilizador | Typosquat detetado, assinatura adulterada |
| HIGH | Avisar e prosseguir | CVE conhecido, pacote com menos de 30 dias |
| MEDIUM | Avisar e prosseguir | Versão com menos de 7 dias, assinatura em falta |
| LOW | Avisar e prosseguir | Gem Ruby sem assinatura (esperado) |
## Como funciona
A skill opera em cinco modos (resumidos abaixo; a fundamentação de design mais profunda está em `skills/safer-dependencies.md`):
### Modo Normal (Manual)
Quando o Claude está prestes a escrever um `import`, adicionar um pacote a um manifesto ou atualizar um ficheiro de bloqueio, a skill é executada inline na sua sessão:
1. Consulta o registo de pacotes por versões estáveis
2. Seleciona automaticamente a versão mais recente publicada há 7+ dias (determinística — sem julgamento de LLM)
3. Verifica vulnerabilidades conhecidas através de ferramentas do ecossistema e da API OSV
4. Verifica assinaturas de pacotes quando disponíveis
5. Emite avisos se forem encontrados problemas, fixa a versão exata
6. Regista o resultado na trilha de auditoria
A seleção de versões é tratada por scripts Python autónomos incluídos na skill, não pelo LLM a interpretar regras. O comando produz `SELECTED: <version>` e o Claude usa exatamente essa versão.
### Modo de Interceção (Automático)
Configure `.claude/settings.json` com um hook `PostToolUse` para ativar a verificação automática e transparente de pacotes:
1. O Claude escreve um ficheiro de manifesto (ex.: `package.json`) com a versão originalmente solicitada — o ficheiro é gravado no disco
2. O hook `PostToolUse` dispara imediatamente após a conclusão da escrita e invoca `safer-dependencies-shim.sh`
3. O shim lê o ficheiro, analisa os pacotes declarados e executa todas as verificações de segurança (typosquat, abandonado, CVE, desatualização, hash-pin)
4. Se forem necessárias correções, o shim **reescreve o manifesto no local** com versões seguras (ou remove entradas que não tenham versão segura)
5. O shim emite sinais (`UPDATED:`, `BLOCKED:`, `WARNING:`, `STALE:`, `MAJOR-UPDATE-CONFIRM:`, `REFACTOR-REQUIRED:`, `REGRESSION:`, `TYPOSQUAT-CONFIRM:`, `VERIFY:`, `CLEAN:`) via `hookSpecificOutput.additionalContext` no stdout. `REGRESSION:` precede um `MAJOR-UPDATE-CONFIRM:` quando o registo de auditoria mostra que o mesmo (ficheiro, pacote) foi anteriormente corrigido para o mesmo alvo seguro — ou seja, um subagente ou um plano desatualizado reintroduziu uma versão com vulnerabilidade conhecida, e o orquestrador deve restaurar a versão previamente aprovada em vez de redecidir o salto de versão principal.
6. O Claude recebe esses sinais como um lembrete de sistema e executa trabalho de acompanhamento (encontrar imports afetados, executar testes, refatorar para alterações disruptivas)
**Nota de design — Forma C (corretiva pós-escrita):** o hook NÃO bloqueia escritas. Cada versão vulnerável é gravada no disco primeiro e depois corrigida automaticamente dentro do mesmo ciclo de uso da ferramenta. Esta é uma escolha deliberada em relação a um design de bloqueio `PreToolUse` — veja [FAQ.md](https://github.com/robert-auger/safer-dependencies/blob/main/FAQ.md#why-posttooluse-post-write-corrective-instead-of-pretooluse-pre-write-blocking-for-the-manifest-path) para os compromissos.
**Exemplo de sinal:**```
UPDATED: aiohttp 3.8.5 → 3.9.0 (HIGH: 33 CVEs fixed)
O agente pai usa esses sinais para identificar código afetado e refatorar conforme necessário.
Configure .claude/settings.json com um hook PreToolUse:Bash para habilitar
auditoria pré-voo de comandos de instalação de gerenciadores de pacotes. Isso complementa
(não substitui) o Modo Interceptação — juntos, eles formam uma defesa em camadas.
npm install [email protected])PreToolUse dispara antes da chamada ser executada e invoca
safer-dependencies-pretooluse-bash.shgit status / ls / npm test pagam
custo desprezível no caminho críticonpm/pnpm/yarn
install/i/add), o helper tokeniza via shlex, extrai cada
argumento pkg@version e faz POST para o OSVpermissionDecision: "deny" com um GHSA-id por achado + CVSS +
resumo, além de uma dica para invocar a skill safer-dependenciesPor que isso existe além do Modo Interceptação: o shim pós-escrita
é cego para Bash. npm install [email protected] é executado até o fim (e
scripts postinstall são executados) antes de qualquer auditoria disparar; npm install -g typosquat-pkg não escreve nenhum manifesto de projeto. O Modo
Pré-Instalação fecha essas lacunas estruturalmente.
O Modo Pré-Instalação só vê o que o usuário digitou (argumentos pkg@version na
linha de comando). Ele não consegue ver a árvore transitiva que o resolvedor
realmente instalará. O Modo Pós-Instalação (abaixo) audita o lockfile assim que
a instalação é concluída — os dois modos são complementares, não redundantes.
Escopo: os CLIs de gerenciadores de pacotes cobertos aqui abrangem cinco ecossistemas
(npm/pnpm/yarn/bun/npx/deno, pip/pip3/pipx/pipenv/uv/uvx/poetry, gem/bundle,
go, cargo), além de Maven via Modo Interceptação (dependências Maven são tipicamente
declaradas em pom.xml/build.gradle, não adicionadas via um verbo CLI).
Lacuna conhecida: o CLI do Maven suporta downloads diretos via
mvn dependency:get -Dartifact=group:art:versionemvn dependency:copy. Este hook ainda não reconhece essas invocações. Se você as usa regularmente, o shim pós-escrita existente ainda captura o que quer que chegue ao seu manifesto, mas a proteção pré-fetch só se aplica aos ecossistemas listados acima. Rastreado como acompanhamento.
Sintaxe reconhecida por ecossistema:
| PM | Verbos | Sintaxe de pin concreto |
|---|---|---|
npm, pnpm, yarn, bun | install, i, add (além de yarn/pnpm dlx, bun x, yarn create) | [email protected], @scope/[email protected] |
npx | (sem verbo — o pacote é o primeiro argumento posicional) | [email protected] |
deno | add, install | npm:[email protected] (specs prefixados com npm) |
pip, pip3, pipx, pipenv, uv, uvx, poetry | install (pip/pip3/pipx/pipenv) / add (uv/poetry) / sem verbo (uvx) | pkg==1.2.3 (extras pkg[extra]==X também são tratados) |
gem, bundle | install (gem) / add | -v 1.2.3, --version 1.2.3, --version=1.2.3 (flag separada) |
go | get, install | [email protected] (deve incluir o prefixo v conforme módulos Go) |
cargo | add, install | [email protected] |
Pins de intervalo (npm ^4.17, pip >=, poetry ^/~, Go @latest) e
versões não especificadas passam para o Modo Interceptação após a instalação — o
shim pós-escrita audita o que o resolvedor escolher. A reescrita automática para uma
versão segura está na fila como acompanhamento.
Modo de falha: fail-open. Qualquer erro (Python ausente, instabilidade de rede, entrada malformada) sai com código 0 e sem saída, permitindo que o bash prossiga. O Modo Interceptação ainda é executado após a instalação, então uma falha pré-voo degrada graciosamente para a proteção existente.
Exemplo de negação:``` safer-dependencies pre-flight audit blocked this install. Vulnerable pinned version(s) detected:
### Modo Pós-Instalação (Hook Bash)
Configure `.claude/settings.json` com um hook `PostToolUse:Bash` para ativar
auditoria pós-execução após comandos Bash. Ele executa **três verificações independentes**
no `cwd` do comando, cada uma cobrindo uma lacuna que os outros hooks não conseguem resolver:
- **Verificação A — arquivos de bloqueio (lockfiles).** Após um verbo de instalação bem-sucedido (`npm install`,
`bundle install`, `poetry install`, `uv sync`, `go mod tidy`, etc.), audita
arquivos de bloqueio recém-modificados (`package-lock.json`, `Gemfile.lock`,
`poetry.lock`, `uv.lock`, `go.sum`, `yarn.lock`, `pnpm-lock.yaml`,
`Pipfile.lock`). Isso cobre a **lacuna de CVEs transitivos** que o Pré-Instalação não
consegue ver: o usuário digitou `pkg@version`, mas o resolvedor pode ter incluído
dezenas de dependências transitivas que ninguém nomeou.
- **Verificação B — manifestos.** Após qualquer comando Bash que *não* esteja em uma
lista de bloqueio somente-leitura (`ls`, `cat`, `git status`, …), audita manifestos
recém-modificados. Este é o **único** mecanismo de fallback para edições de manifestos feitas via `sed -i`, `jq`, ou
um script — essas ignoram a ferramenta `Write`/`Edit` na qual o Modo Interceptação se baseia.
- **Verificação C — ambiente resolvido.** Um simples `pip install` /
`pip install -r requirements.txt` não grava arquivo de bloqueio, então a Verificação A nunca vê
a árvore resolvida. Após uma instalação no formato pip, a Verificação C reexecuta o mesmo
pip com um `list --format=json` somente-leitura e verifica via OSV todo o ambiente
resolvido (direto + transitivo).
Como uma verificação é executada:
1. Claude executa uma chamada de ferramenta Bash
2. O hook `PostToolUse` dispara *após* o comando ser concluído e invoca
`safer-dependencies-posttooluse-bash.sh`
3. Um filtro inicial puro em Bash encurta comandos que não correspondem a nenhum gatilho de verificação em
~115 ms (mesma convenção de caminho rápido do Pré-Instalação), então `ls` / `git` / `cat`
têm custo desprezível
4. Cada verificação percorre o `cwd` com `find -maxdepth 5` (cobre layouts de monorepo;
exclui `node_modules`, `.git`, `.venv`, `venv`) em busca de arquivos modificados nos
últimos 60 s — substituível via `SAFE_DEP_POSTINSTALL_MTIME_WINDOW`
5. Para cada arquivo recém-modificado (Verificação A/B), o hook forja um payload sintético
de `PostToolUse:Write` e o envia ao shim existente — os auditores de arquivos de bloqueio e
manifestos do shim são executados sem alterações, sem lógica duplicada
6. Os sinais por arquivo são concatenados e emitidos como um único JSON de `hookSpecificOutput`
para o agente pai
**O que ele detecta que o Pré-Instalação não detecta:** vulnerabilidades transitivas.
Um `bundle install` de aparência limpa pode incluir `[email protected]` (CVE-2025-27610)
como dependência transitiva de `sinatra` — o usuário nunca digitou `rack`, então
o Pré-Instalação não consegue ver, mas o Pós-Instalação lê o
`Gemfile.lock` resolvido e reporta a CVE.
**Escopo:** a Verificação A não reescreve versões resolvidas — o contrato de
autocorreção se aplica apenas a manifestos que o Claude escreveu diretamente. Para CVEs transitivos,
a correção normalmente é "atualizar a dependência direta que possui a transitiva", o que
exige julgamento humano. A Verificação B *faz* autocorreção, pois audita manifestos
pelo mesmo caminho de shim do Modo Interceptação. A Verificação A é ignorada quando o
nível de verificação `transitive` está definido como `off` (`config set checks.transitive off`).
**Modo de falha:** fail-open, igual aos outros hooks. Qualquer erro (shim
ausente, payload malformado, Python indisponível) sai com código 0 silenciosamente.
**Exemplo de AVISO:**```
WARNING: [email protected] in lock file has GHSA-29mw-wpgm-hmr9, GHSA-35jh-r3h4-6jhm
Os quatro modos acima só disparam para chamadas de ferramentas da sessão raiz. Quando a sessão raiz despacha um subagente (via a ferramenta Agent — muitas skills e comandos de barra fazem isso internamente), as chamadas Write/Edit/Bash do subagente ignoram todos eles. O Modo Pós-Agente é a rede de segurança reativa para essa lacuna.
PreToolUse:Agent (safer-dependencies-pretooluse-agent.sh) é executado imediatamente antes de cada despacho de Agent e toca um arquivo sentinela em /tmp/.safer-deps-agent-<PPID>-<session_id>.sentinel (recorrendo a um nome apenas com PPID quando não há id de sessão disponível)PostToolUse:Agent (safer-dependencies-posttooluse-agent.sh) é executado após a chamada do Agent retornar, faz find em todo manifest e lockfile mais recente que o sentinela e audita cada um pelo mesmo caminho do shimadditionalContext para a próxima rodada da sessão raiz; o sentinela é removidoSubagentes aninhados são cobertos automaticamente — o PostToolUse:Agent da raiz só dispara depois que todo o trabalho do agente externo (incluindo qualquer coisa que ele tenha despachado) está em disco. A única lacuna é uma instalação global que não escreve manifest nem lockfile (npm install -g …): não há nada para escanear. Como os outros hooks, ele falha aberto — qualquer erro (sentinela ausente, shim ausente, payload ilegível) sai com código 0 silenciosamente. A justificativa completa do design está em skills/safer-dependencies.md.
Cada verificação é registrada em ~/.claude/safer-dependencies-audit-YYYY-MM.log (um arquivo por mês calendário, onde YYYY-MM é o ano-mês UTC) como uma única linha JSON. Substitua o caminho completo com a variável de ambiente SAFE_DEP_AUDIT_LOG (quando definida, o sufixo de data não é anexado). Os arquivos também sofrem rotação por tamanho quando excedem SAFE_DEP_LOG_MAX_BYTES (padrão 10 MiB; defina como 0 para desativar). Defina SAFE_DEP_MODEL para substituir o valor do modelo gravado em source.model em cada entrada — útil para comparações A/B entre versões de modelo.
Todos os cinco modos anexam ao mesmo arquivo. Cada entrada carrega um bloco source (esquema 2.2) identificando qual componente o escreveu:
source.component | Escrito por | Gatilho |
|---|---|---|
shim.posttooluse | shim.sh | Gravação de manifest ou lockfile (Modo Interceptação, despacho pós-instalação) |
shim.install_error | shim.sh | Falha de instalação de preflight do shim |
bash.pretooluse | pretooluse-bash.sh | Comando de instalação Bash (Modo Pré-Instalação) |
bash.posttooluse | posttooluse-bash.sh | O próprio hook Bash Pós-Instalação, quando falha aberto antes de alcançar o shim |
agent.pretooluse | pretooluse-agent.sh | Reservado para eventos de falha aberta Pré-Agente (o próprio hook é atualmente silencioso em sucesso) |
agent.posttooluse | posttooluse-agent.sh | Eventos de falha aberta do hook Pós-Agente (ex.: shim ausente, python_missing) |
manual.skill | Claude executando Modo Normal | Auditoria manual invocada inline |
source.model registra o modelo do Claude Code ativo na sessão (ex.: "claude-sonnet-4-6"). Presente no esquema 2.1+; entradas escritas por instalações mais antigas omitem o campo. O comando de estatísticas degrada graciosamente para "unknown" quando ele está ausente.
Filtre por source.component com 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
Para uma análise mais fácil, peça ao Claude estatísticas de uso em vez de analisar os logs manualmente:```
"Show safer-dependencies stats for the last month"
Este fornece resumos legíveis por humanos de atividade, impacto de segurança e métricas de desempenho extraídos desses logs de auditoria.
Formatos de entrada (esquema 2.2). Três formatos distintos compartilham o mesmo cabeçalho ts / schema / source:
| Formato | Quando é gravado | Campos distintivos |
|---|---|---|
| Entrada de auditoria | Auditoria de manifesto / lockfile / instalação via bash | file, ecosystem, checked, findings, abandoned, stale, typosquat, unknown, signatures, notes, clean |
| Entrada de erro de instalação | Erro de instalação no preflight do shim (componente shim.install_error) | install_error, shim_dir, scripts_dir |
| Entrada de fail-open | Qualquer ponto de entrada de hook sai antecipadamente devido a helper_missing / shim_missing / python_missing. source.mode é "fail_open" | fail_open: { reason, detail? } |
Entradas de auditoria: o Modo de Interceptação executa o pipeline completo (proveniência, idade da versão, OSV, abandonado/obsoleto, typosquat, assinaturas), portanto todos os arrays podem ser preenchidos. O Modo Pré-Instalação executa apenas OSV hoje, então abandoned / stale / typosquat / signatures estão sempre vazios. O despacho pós-instalação (auditoria de lockfile) grava sob shim.posttooluse com findings preenchido por strings WARNING: dos auditores de lockfile. O array notes carrega sinais informativos NOTE: (por exemplo, manifesto-ignorado-porque-não-pinned).
O esquema 2.2 adicionou — de forma aditiva — quatro campos às entradas de auditoria de lockfile: lockfile, manifest_ref, relation_summary (uma classificação direta/transitiva/desconhecida de cada pacote sinalizado em relação ao manifesto irmão) e um bloco policy registrando o nível transitive em vigor. O incremento é retrocompatível: leitores de entradas 2.1 toleram os novos campos, e o campo source.model permanece presente a partir da versão 2.1 em diante.```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]"]
}
Pré-Modo de Instalação exemplo (hook Bash, pino vulnerável negado):```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 Mode example (hook Bash pós-instalação chamado sem shim adjacente — instalação quebrada):```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" } }
Uma entrada de fail-open diz: "este hook foi acionado, mas saiu cedo sem auditar porque faltava algum pré-requisito." Use o filtro jq acima (`select(.source.mode == "fail_open")`) para revelar cada evento silencioso de perda de proteção no seu log.
Quando o shim é executado em modo dry-run (`SAFE_DEP_DRY_RUN=1`), as entradas também incluem `"mode": "dry_run"` para que a análise posterior possa filtrar invocações apenas de auditoria.
## Requisitos
- Python 3.9+ (os hooks verificam isso e fazem fail-open em interpretadores mais antigos)
- `curl` (para chamadas de API do registry e verificações de vulnerabilidade OSV)
- Ferramentas de ecossistema (opcionais, a skill recorre à API OSV se estiverem ausentes):
- `npm` para pacotes npm
- `pip-audit` para pacotes Python
- `bundle` para pacotes Ruby
- `dependency-check` para pacotes Java
## FAQ
A justificativa das decisões de design (por que `PostToolUse` em vez de `PreToolUse`, por que assinaturas não são verificadas, por que scripts e shim são duplicados, pegadinhas de carregamento de skill, etc.) está documentada em [`FAQ.md`](https://github.com/robert-auger/safer-dependencies/blob/main/FAQ.md).