
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.
# Dependências Mais Seguras para o Claude Code 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](https://github.com/robert-auger/safer-dependencies/blob/main/CAPABILITIES.md) para saber exatamente o que é e o que não é coberto. > **Novo aqui?** [GETTING-STARTED.md](https://github.com/robert-auger/safer-dependencies/blob/main/GETTING-STARTED.md) leva você do zero a uma instalação funcional em cerca de cinco minutos. > **Segurança e privacidade:** consulte [SECURITY.md](https://github.com/robert-auger/safer-dependencies/blob/main/SECURITY.md) (divulgação de vulnerabilidades), [PRIVACY.md](https://github.com/robert-auger/safer-dependencies/blob/main/PRIVACY.md) (saída de dados, sem telemetria) e [CAPABILITIES.md](https://github.com/robert-auger/safer-dependencies/blob/main/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 **apenas** para monetizar o software *em si* — 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 **[LICENSE](https://github.com/robert-auger/safer-dependencies/blob/main/LICENSE)** (Seção 4 para a restrição comercial); solicitações de licença comercial via [github.com/robert-auger](https://github.com/robert-auger). ## Conteúdo - [Introdução](#getting-started) — do zero à instalação em cerca de cinco minutos - [O que ele faz](#what-it-does) - [O que o aciona](#what-triggers-it) - [O que há neste repositório](#whats-in-this-repo) - [Ecossistemas suportados](#supported-ecosystems) - [Instalação](#install) - [Configuração](#configuration) - [Alterando o período de espera](#changing-the-cooldown-period) - [Níveis de aviso](#warning-levels) - [Como funciona](#how-it-works) - [Modo Normal (Manual)](#normal-mode-manual) - [Modo de Interceptação (Automático)](#intercept-mode-automatic) - [Modo Pré-Instalação (Hook Bash)](#pre-install-mode-bash-hook) - [Modo Pós-Instalação (Hook Bash)](#post-install-mode-bash-hook) - [Modo Pós-Agente (Par de Hooks de Agente)](#post-agent-mode-agent-hook-pair) - [Registro de auditoria](#audit-log) - [Requisitos](#requirements) - [FAQ](#faq) ## Introdução **[GETTING-STARTED.md](https://github.com/robert-auger/safer-dependencies/blob/main/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](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#permissions-allowlist), atualização e desinstalação), consulte **[INSTALLATION.md](https://github.com/robert-auger/safer-dependencies/blob/main/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"*. ## O que ele faz Quando o Claude está prestes a adicionar um pacote ao seu projeto, o safer-dependencies intercepta e executa 5 verificações: 1. **Proveniência** — registro oficial, detecção de typosquat (npm/PyPI/RubyGems/Maven/crates.io), idade do pacote 2. **Idade da versão** — escolhe a versão estável mais recente publicada há 7+ dias (janela de espera) 3. **Varredura de vulnerabilidades** — API OSV, com ferramentas nativas do ecossistema (npm audit, pip-audit, bundle audit) quando disponíveis 4. **Integridade de pin de hash** — para linhas de `requirements.txt` do PyPI com pins `--hash=sha256:...`, o hash declarado é validado contra os hashes publicados do PyPI; uma incompatibilidade emite um AVISO 5. **Pacotes abandonados e desatualizados** — pacotes conhecidamente abandonados (ex.: `paperclip`, `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). ## O que o aciona A skill é acionada automaticamente quando o Claude: **Operações de manifesto / instalação** - Adiciona ou atualiza um pacote em `package.json`, `requirements.txt`, `Gemfile`, `pom.xml`, `build.gradle`, `Cargo.toml`, `go.mod` ou qualquer outro manifesto suportado - Escreve um `import`, `require` ou `use` para um pacote ainda não declarado no manifesto - Gera ou atualiza um arquivo de bloqueio (verifica apenas entradas novas/alteradas) - Executa uma instalação do gerenciador de pacotes via Bash (`npm 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 resultante - Escreve um `Dockerfile` ou fluxo de trabalho de CI (`.github/workflows/*.yml`, etc.) que incorpora etapas de instalação fixadas do gerenciador de pacotes **Perguntas de seleção e recomendação** - Comparações de bibliotecas/frameworks: "devo usar axios ou node-fetch?", "moment vs dayjs?", "qual é melhor X ou Y?" - Solicitações de recomendação: "qual é um bom cliente HTTP para Python?", "recomende uma biblioteca de logging para Go", "qual pacote lida com CSV no Node?" - Seleção de versão: "qual versão do Django devo usar?", "Flask estável mais recente?" **Expressões de intenção de uso (pré-adição)** - "Quero usar FastAPI para isso", "estou pensando em adicionar Celery", "estamos considerando Prisma como o ORM", "vamos usar Tailwind" **Perguntas sobre saúde e confiança de pacotes** - "O moment.js ainda é mantido?", "este gem ainda está ativo?", "X está abandonado?", "X está em fim de vida?", "posso confiar neste pacote?", "quando o faker foi atualizado pela última vez?" **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)** - "Adicione cache Redis ao aplicativo", "conecte ao Postgres", "adicione autenticação JWT", "escreva código para enviar e-mails" — dispara quando nenhum pacote para essa capacidade já está no manifesto **Migração e portabilidade** - "Migre de requests para httpx", "mude de CRA para Vite", "porte de moment para date-fns" — audita o pacote de entrada Ele **não** dispara para: - Imports da biblioteca padrão (`os`, `fs`, `java.util.*`, etc.) - Dependências já declaradas que não estão sendo alteradas - Discussão acadêmica sobre como um pacote funciona internamente ("explique o reconciler do React", "como funciona a resolução de módulos do webpack?") — perguntas de comparação e seleção ainda disparam - Instalação de aplicativos de nível de sistema operacional, runtimes ou extensões de IDE (o próprio Python, Docker, Homebrew, extensões do VS Code) ## O que há neste repositório 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](https://github.com/robert-auger/safer-dependencies/blob/main/FAQ.md#why-a-skill-alone-is-not-sufficient) para saber por que uma skill sozinha não pode garantir cobertura.) ## Ecossistemas suportados | 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` | ## Instalação Novo no projeto? Comece com **[GETTING-STARTED.md](https://github.com/robert-auger/safer-dependencies/blob/main/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. ### Modo Pré-Instalação (Hook Bash) 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. 1. Claude tenta uma chamada de ferramenta Bash (ex.: `npm install [email protected]`) 2. O hook `PreToolUse` dispara antes da chamada ser executada e invoca `safer-dependencies-pretooluse-bash.sh` 3. Um filtro inicial puramente em bash encurta comandos que não são de gerenciadores de pacotes em ~115 ms (sem invocação de Python), então `git status` / `ls` / `npm test` pagam custo desprezível no caminho crítico 4. Para instalações reconhecidas de gerenciadores de pacotes (`npm`/`pnpm`/`yarn` `install`/`i`/`add`), o helper tokeniza via `shlex`, extrai cada argumento `pkg@version` e faz POST para o OSV 5. Qualquer pin concreto vulnerável → o hook retorna `permissionDecision: "deny"` com um GHSA-id por achado + CVSS + resumo, além de uma dica para invocar a skill safer-dependencies 6. A instalação nunca é executada — sem fetch de rede, sem scripts postinstall **Por 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:version` e `mvn 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: - [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. ``` ### 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 ``` ### Modo Pós-Agente (Par de Hooks de Agente) 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. 1. Um hook `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) 2. O subagente é executado e pode escrever manifests ou lockfiles 3. Um hook `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 shim 4. Os achados surgem como `additionalContext` para a próxima rodada da sessão raiz; o sentinela é removido Subagentes 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`. ## Log de auditoria 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 | --- [Read more](https://github.com/robert-auger/safer-dependencies)