
Livello di sicurezza automatico delle dipendenze per assistenti di codifica AI che controlla i pacchetti per CVE, typosquatting, abbandono, problemi di vetustà delle versioni e integrità degli hash negli ecosistemi npm, PyPI, RubyGems, Maven, Go e Rust.
Quando assistenti di codifica AI come Claude aggiungono pacchetti al tuo progetto, spesso scelgono qualunque versione sembri giusta — senza verificare se ha vulnerabilità di sicurezza note, se il pacchetto è ancora mantenuto attivamente, o se il nome è a un typo di distanza da un sosia malevolo.
safer-dependencies è un layer di sicurezza per Claude Code: si posiziona tra Claude e i tuoi file manifest ed esegue i suoi controlli di sicurezza automaticamente: le installazioni vulnerabili vengono bloccate prima di essere eseguite, e una versione rischiosa scritta in un manifest viene corretta su disco subito dopo la scrittura. Rileva e corregge le dipendenze rischiose — CVE, typosquatting, pacchetti abbandonati e problemi di età della versione, più un periodo di cooldown per le release appena pubblicate — su npm, PyPI, RubyGems, Maven, Go, Rust e PHP (Composer). Consulta CAPABILITIES.md per sapere esattamente cosa è coperto e cosa no.
Nuovo qui? GETTING-STARTED.md ti porta da zero a un'installazione funzionante in circa cinque minuti.
Sicurezza e privacy: consulta SECURITY.md (divulgazione delle vulnerabilità), PRIVACY.md (trasferimento dati in uscita, nessuna telemetria) e CAPABILITIES.md (ciò che lo strumento difende e ciò che non difende).
Licenza (source-available — NON OSI "open source"): Uso e modifica liberi per i tuoi scopi, incluso l'uso a scopo di lucro, l'uso interno aziendale e la creazione di prodotti che vendi. Una licenza a pagamento separata è richiesta solo per monetizzare il software stesso — venderlo, distribuirlo all'interno di un prodotto o servizio venduto, o offrirne le funzionalità a terzi a pagamento (incluso hosted/SaaS/API). La ridistribuzione e i derivati devono mantenere la licenza e attribuire il credito a questo progetto. Consulta LICENSE (Sezione 4 per la restrizione commerciale); richieste di licenza commerciale via github.com/robert-auger.
GETTING-STARTED.md ti porta da zero a un'installazione funzionante in circa cinque minuti — prerequisiti, installazione interattiva e verifica. Per il riferimento completo all'installazione (installazioni globali/di progetto/manuali, specifiche Windows, la allowlist dei permessi, aggiornamento e disinstallazione), consulta INSTALLATION.md.
Uso quotidiano: una volta installati gli hook, non c'è nulla da eseguire — safer-dependencies funziona automaticamente in background. Mentre Claude aggiunge o installa pacchetti, segnala le dipendenze rischiose e aggiorna le versioni vulnerabili a una sicura sul posto — e blocca un'installazione nota come vulnerabile prima ancora che venga eseguita — così i pacchetti non sicuri vengono individuati e corretti senza che tu debba chiederlo. Puoi comunque invocarlo direttamente in qualsiasi momento: "[email protected] è sicuro?", "controlla la configurazione di safer-dependencies", o "mostra le statistiche di safer-dependencies".
Quando Claude sta per aggiungere un pacchetto al tuo progetto, safer-dependencies intercetta ed esegue 5 controlli:
requirements.txt di PyPI con pin --hash=sha256:..., l'hash dichiarato viene validato rispetto agli hash pubblicati da PyPI; una mancata corrispondenza genera un WARNINGpaperclip, request, pycrypto, github.com/dgrijalva/jwt-go) vengono bloccati immediatamente con un sostituto suggerito; i pacchetti senza release stabile da 2+ anni ricevono un avviso STALE: consultivo. I pacchetti hard-bloccati vengono rimossi dal manifest e Claude chiederà come procedere; i pacchetti solo stale vengono lasciati al loro posto.Se vengono trovati problemi, Claude emette avvisi e può ripiegare su una versione più sicura. Tutti i controlli vengono registrati in ~/.claude/safer-dependencies-audit-YYYY-MM.log (un file per mese di calendario).
La skill opera in cinque modalità (riassunte di seguito; le motivazioni di design più approfondite si trovano in skills/safer-dependencies.md):
Quando Claude sta per scrivere un import, aggiungere un pacchetto a un manifest o aggiornare un file di lock, la skill viene eseguita inline nella tua sessione:
La selezione della versione è gestita da script Python autonomi inclusi nella skill, non dall'LLM che interpreta regole. Il comando restituisce SELECTED: <version> e Claude usa esattamente quella versione.
Configura .claude/settings.json con un hook PostToolUse per abilitare la verifica automatica e trasparente dei pacchetti:
package.json) con la versione originariamente richiesta — il file viene salvato su discoPostToolUse scatta immediatamente dopo il completamento della scrittura e invoca safer-dependencies-shim.shUPDATED:, BLOCKED:, WARNING:, STALE:, MAJOR-UPDATE-CONFIRM:, REFACTOR-REQUIRED:, REGRESSION:, TYPOSQUAT-CONFIRM:, VERIFY:, ) tramite su stdout. precede un quando il registro di audit mostra che la stessa coppia (file, pacchetto) era stata precedentemente corretta allo stesso target sicuro — vale a dire, un subagent o un piano obsoleto ha reintrodotto una versione nota come vulnerabile, e l'orchestratore dovrebbe ripristinare la versione precedentemente approvata piuttosto che ridecidere il major bump.Nota di design — Shape C (correttivo post-scrittura): l'hook NON blocca le scritture. Ogni versione vulnerabile viene prima salvata su disco e poi corretta automaticamente nello stesso ciclo di tool-use. Questa è una scelta deliberata rispetto a un design bloccante PreToolUse — consulta FAQ.md per i compromessi.
Esempio di segnale:``` UPDATED: aiohttp 3.8.5 → 3.9.0 (HIGH: 33 CVEs fixed)
L'agente padre usa questi segnali per identificare il codice interessato e rifattorizzarlo secondo necessità.
### Modalità Pre-Install (Bash Hook)
Configura `.claude/settings.json` con un hook `PreToolUse:Bash` per abilitare
il controllo pre-flight dei comandi di installazione dei package manager. Questo
integra (non sostituisce) la Modalità Intercept — insieme formano una difesa a strati.
1. Claude tenta una chiamata tool Bash (ad es. `npm install [email protected]`)
2. L'hook `PreToolUse` scatta prima che la chiamata venga eseguita e invoca
`safer-dependencies-pretooluse-bash.sh`
3. Un filtro anticipato in puro bash cortocircuita i comandi non-PM in ~115 ms
(nessuna invocazione di Python), quindi `git status` / `ls` / `npm test` hanno
un costo trascurabile sul percorso critico
4. Per le installazioni riconosciute dei package manager (`npm`/`pnpm`/`yarn`
`install`/`i`/`add`), l'helper tokenizza tramite `shlex`, estrae ogni
argomento `pkg@version` e lo invia in POST a OSV
5. Qualsiasi pin concreto vulnerabile → l'hook restituisce
`permissionDecision: "deny"` con per ogni riscontro un GHSA-id + CVSS +
sommario, più un suggerimento a invocare la skill safer-dependencies
6. L'installazione non viene mai eseguita — nessun fetch di rete, nessuno script postinstall
**Perché esiste oltre alla Modalità Intercept:** lo shim post-write
è cieco a Bash. `npm install [email protected]` viene eseguito fino in fondo (e
gli script postinstall vengono eseguiti) prima che qualsiasi audit scatti; `npm install -g
typosquat-pkg` non scrive alcun manifest di progetto. La Modalità Pre-Install
chiude queste lacune strutturalmente.
La Modalità Pre-Install vede solo ciò che l'utente ha **digitato** (argomenti `pkg@version` sulla
riga di comando). Non può vedere l'albero transitivo che il resolver
installerà realmente. La **Modalità Post-Install** (sotto) controlla il lockfile una volta
completata l'installazione — le due modalità sono complementari, non ridondanti.
**Ambito:** le CLI dei package manager qui coperte abbracciano cinque ecosistemi
(npm/pnpm/yarn/bun/npx/deno, pip/pip3/pipx/pipenv/uv/uvx/poetry, gem/bundle,
go, cargo), più Maven tramite Modalità Intercept (le dipendenze Maven sono tipicamente
dichiarate in `pom.xml`/`build.gradle`, non aggiunte tramite un verbo CLI).
> **Lacuna nota:** la CLI Maven supporta download diretti tramite
> `mvn dependency:get -Dartifact=group:art:version` e `mvn dependency:copy`.
> Questo hook non riconosce ancora tali invocazioni. Se le usi
> regolarmente, lo shim post-write esistente cattura comunque ciò che finisce nel
> tuo manifest, ma la protezione pre-fetch si applica solo agli
> ecosistemi sopra elencati. Tracciato come follow-up.
Sintassi riconosciuta per ecosistema:
| PM | Verbi | Sintassi del pin concreto |
|---|---|---|
| `npm`, `pnpm`, `yarn`, `bun` | `install`, `i`, `add` (inoltre `yarn`/`pnpm dlx`, `bun x`, `yarn create`) | `[email protected]`, `@scope/[email protected]` |
| `npx` | (senza verbo — il pacchetto è il primo argomento posizionale) | `[email protected]` |
| `deno` | `add`, `install` | `npm:[email protected]` (specifiche con prefisso npm) |
| `pip`, `pip3`, `pipx`, `pipenv`, `uv`, `uvx`, `poetry` | `install` (pip/pip3/pipx/pipenv) / `add` (uv/poetry) / senza verbo (uvx) | `pkg==1.2.3` (gestiti anche gli extras `pkg[extra]==X`) |
| `gem`, `bundle` | `install` (gem) / `add` | `-v 1.2.3`, `--version 1.2.3`, `--version=1.2.3` (flag separato) |
| `go` | `get`, `install` | `[email protected]` (deve includere il prefisso `v` per i moduli Go) |
| `cargo` | `add`, `install` | `[email protected]` |
Pin di intervallo (npm `^4.17`, pip `>=`, poetry `^`/`~`, Go `@latest`) e
versioni non specificate passano alla Modalità Intercept dopo l'installazione — lo
shim post-write controlla ciò che il resolver sceglie. La riscrittura automatica a una
versione sicura è in coda come follow-up.
**Modalità di errore:** fail-open. Qualsiasi errore (Python mancante, blip di rete,
input malformato) esce con 0 e nessun output, permettendo a bash di proseguire.
La Modalità Intercept viene comunque eseguita dopo l'installazione, quindi un pre-flight fallito
ricade in modo pulito sulla protezione esistente.
**Esempio di deny:**```
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.
Configura .claude/settings.json con un hook PostToolUse:Bash per abilitare
l'audit post-esecuzione dopo i comandi Bash. Esegue tre scan indipendenti
sulla cwd del comando, ciascuno dei quali colma una lacuna che gli altri hook non possono coprire:
npm install,
bundle install, poetry install, uv sync, go mod tidy, ecc.), controlla
i file di lock modificati di recente (package-lock.json, Gemfile.lock,
poetry.lock, uv.lock, go.sum, yarn.lock, pnpm-lock.yaml,
Pipfile.lock). Questo colma la lacuna delle CVE transitive che Pre-Install
non può vedere: l'utente ha digitato pkg@version, ma il resolver potrebbe aver
incluso decine di dipendenze transitive mai nominate.Come funziona uno scan:
PostToolUse scatta dopo il completamento del comando e invoca
safer-dependencies-posttooluse-bash.shls / git / cat hanno un costo trascurabilecwd con find -maxdepth 5 (copre i layout monorepo;
esclude node_modules, .git, .venv, venv) per i file modificati negli
ultimi 60 s — sovrascrivibile tramite SAFE_DEP_POSTINSTALL_MTIME_WINDOWPostToolUse:Write e lo inoltra allo shim esistente — gli auditor di lockfile
e manifesti dello shim vengono eseguiti invariati, senza logica duplicataCosa intercetta che Pre-Install non intercetta: vulnerabilità transitive.
Un bundle install dall'aspetto pulito può includere [email protected] (CVE-2025-27610)
come transitiva di sinatra — l'utente non ha mai digitato rack, quindi
Pre-Install non può vederla, ma Post-Install legge il Gemfile.lock risolto
e segnala la CVE.
Ambito: Scan A non riscrive le versioni risolte — il contratto di
autocorrezione si applica solo ai manifesti scritti direttamente da Claude.
Per le CVE transitive, la soluzione è in genere "aggiorna la dipendenza diretta
che possiede la transitiva", il che richiede giudizio umano. Scan B fa
autocorrezione, perché controlla i manifesti attraverso lo stesso percorso shim
della Intercept Mode. Scan A viene saltato quando il livello di controllo
transitive è impostato su off (config set checks.transitive off).
Modalità di errore: fail-open, come gli altri hook. Qualsiasi errore (shim mancante, payload malformato, Python non disponibile) termina con codice 0 in silenzio.
Esempio di WARNING:``` WARNING: [email protected] in lock file has GHSA-29mw-wpgm-hmr9, GHSA-35jh-r3h4-6jhm
### Modalità Post-Agente (Coppia di Hook per Agent)
Le quattro modalità sopra scattano solo per le chiamate agli strumenti della **sessione root**. Quando la sessione root lancia un subagente (tramite lo strumento `Agent` — molte skill e comandi slash lo fanno internamente), le chiamate Write/Edit/Bash del subagente aggirano tutte queste modalità. La Modalità Post-Agente è la rete di sicurezza reattiva per questa lacuna.
1. Un hook `PreToolUse:Agent` (`safer-dependencies-pretooluse-agent.sh`) viene eseguito
immediatamente prima di ogni invio di Agent e tocca un file sentinella in
`/tmp/.safer-deps-agent-<PPID>-<session_id>.sentinel` (ripiegando su un
nome basato solo sul PPID quando non è disponibile un ID di sessione)
2. Il subagente viene eseguito e può scrivere manifest o lockfile
3. Un hook `PostToolUse:Agent` (`safer-dependencies-posttooluse-agent.sh`) viene eseguito
dopo che la chiamata ad Agent restituisce il controllo, cerca con `find` ogni manifest e lockfile più recente della
sentinella e controlla ciascuno tramite lo stesso percorso shim
4. I risultati emergono come `additionalContext` per il turno successivo della sessione root; la
sentinella viene rimossa
I subagenti annidati sono coperti automaticamente — il `PostToolUse:Agent` della root
scatta solo dopo che tutto il lavoro dell'agente esterno (incluso qualsiasi cosa *lui* abbia
lanciato) è su disco. L'unica lacuna è un'installazione globale che non scrive alcun
manifest o lockfile (`npm install -g …`): non c'è nulla da scansionare. Come gli
altri hook, fallisce in modalità aperta — qualsiasi errore (sentinella mancante, shim mancante,
payload illeggibile) esce con 0 silenziosamente. La logica progettuale completa è in
`skills/safer-dependencies.md`.
## Cosa lo attiva
La skill scatta automaticamente quando Claude:
**Operazioni su manifest / installazioni**
- Aggiunge o aggiorna un pacchetto in `package.json`, `requirements.txt`, `Gemfile`, `pom.xml`, `build.gradle`, `Cargo.toml`, `go.mod` o qualsiasi altro manifest supportato
- Scrive un `import`, `require` o `use` per un pacchetto non ancora dichiarato nel manifest
- Genera o aggiorna un lock file (controlla solo le voci nuove/modificate)
- Esegue un'installazione del gestore pacchetti tramite Bash (`npm install`, `bundle install`, `poetry install`, `uv sync`, `go mod tidy`, ecc.) — Pre-Install controlla gli argomenti del comando, Post-Install controlla il lockfile risultante
- Scrive un `Dockerfile` o una workflow CI (`.github/workflows/*.yml`, ecc.) che incorpora passi di installazione bloccati del gestore pacchetti
**Domande di selezione e raccomandazione**
- Confronti tra librerie/framework: "dovrei usare axios o node-fetch?", "moment vs dayjs?", "quale è meglio X o Y?"
- Richieste di raccomandazione: "qual è un buon client HTTP per Python?", "consiglia una libreria di logging per Go", "quale pacchetto gestisce CSV in Node?"
- Selezione della versione: "quale versione di Django dovrei usare?", "l'ultima Flask stabile?"
**Espressioni di intenzione d'uso (pre-aggiunta)**
- "Voglio usare FastAPI per questo", "sto pensando di aggiungere Celery", "stiamo valutando Prisma come ORM", "usiamo Tailwind"
**Domande su salute e affidabilità dei pacchetti**
- "moment.js è ancora mantenuto?", "questa gem è ancora attiva?", "X è abbandonato?", "X è a fine vita (EOL)?", "posso fidarmi di questo pacchetto?", "quando è stato aggiornato l'ultima volta faker?"
**Comandi di scaffolding**
- `npx create-react-app`, `npm create vite@latest`, `django-admin startproject`, `rails new`, `cargo new` + `cargo add`, "bootstrap di un nuovo progetto FastAPI"
**Aggiunte implicite di pacchetti (richieste di funzionalità che implicano una nuova dipendenza)**
- "Aggiungi la cache Redis all'app", "connettiti a Postgres", "aggiungi autenticazione JWT", "scrivi codice per inviare email" — scatta quando nessun pacchetto per quella funzionalità è già nel manifest
**Migrazione e porting**
- "Migra da requests a httpx", "passa da CRA a Vite", "porta da moment a date-fns" — controlla il pacchetto in arrivo
Non scatta per:
- Import di librerie standard (`os`, `fs`, `java.util.*`, ecc.)
- Dipendenze già dichiarate che non vengono modificate
- Discussioni accademiche sul funzionamento interno di un pacchetto ("spiega il reconciler di React", "come funziona la risoluzione dei moduli di webpack?") — le domande di confronto e selezione invece scattano comunque
- Installazione di app a livello di sistema operativo, runtime o estensioni IDE (Python stesso, Docker, Homebrew, estensioni VS Code)
## Cosa c'è in questo repository
Questo è un **bundle di skill + hook**, non un singolo file di skill. Un'installazione completa distribuisce questi componenti:
| File | Ruolo |
|---|---|
| `skills/safer-dependencies.md` | La **skill** (`SKILL.md` una volta installata). Descrive le procedure di audit e include la modalità di gestione per installazione/statistiche. |
| `skills/safer-dependencies-shim.sh` | Hook `PostToolUse:Write`/`Edit` — controlla le scritture di manifest e lockfile e corregge automaticamente le versioni vulnerabili sul posto (Modalità Intercetta). |
| `skills/safer-dependencies-pretooluse-bash.sh` | Hook `PreToolUse:Bash` — audit OSV pre-volo dei comandi di installazione del gestore pacchetti; blocca i pin concreti vulnerabili prima che l'installazione venga eseguita (Modalità Pre-Install). |
| `skills/safer-dependencies-posttooluse-bash.sh` | Hook `PostToolUse:Bash` — audit post-volo dopo i comandi Bash; intercetta CVE transitive nei lockfile appena scritti, nei manifest modificati tramite `sed`/`jq`/script e nell'ambiente risolto di un semplice `pip install` (Modalità Post-Install). |
| `skills/safer-dependencies-pretooluse-agent.sh` + `skills/safer-dependencies-posttooluse-agent.sh` | Coppia di hook `PreToolUse:Agent` + `PostToolUse:Agent` — chiude la lacuna di copertura dei subagenti. Le modalità 2–4 scattano solo per le chiamate agli strumenti della sessione root, quindi qualsiasi manifest scritto da un subagente le aggira. Post-Agente controlla tutto ciò che il subagente ha scritto dopo che ogni chiamata allo strumento Agent restituisce il controllo (Modalità Post-Agente). |
| `skills/scripts/` | Libreria Python condivisa (`safedep/`) e script resolver standalone usati da tutti gli hook. |
| `skills/scripts/safer_dependencies_manager.py` | Modulo di gestione per installazione interattiva, statistiche d'uso e validazione della configurazione. |
Il solo file della skill non basta — senza gli hook, l'invocazione automatica dipende dalla decisione di Claude di ricorrere alla skill. Installa tutti e cinque i componenti per una copertura completa; molte skill e comandi slash lanciano subagenti internamente, quindi la coppia Post-Agente conta anche se non ne generi mai esplicitamente uno. (Vedi [FAQ.md](https://github.com/robert-auger/safer-dependencies/blob/HEAD/FAQ.md#why-a-skill-alone-is-not-sufficient) per il motivo per cui una skill da sola non può garantire la copertura.)
## Ecosistemi supportati
| Ecosistema | Manifest | Lock file |
|-----------|----------|-----------|
| 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` |
## Installazione
Nuovo al progetto? Inizia con **[GETTING-STARTED.md](https://github.com/robert-auger/safer-dependencies/blob/HEAD/GETTING-STARTED.md)**. La versione breve:```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
L'installer chiede l'ambito (globale o di progetto) e quali hook abilitare, poi scrive settings.json per te — sia le voci degli hook che l'allowlist dei permessi che consente ai comandi di controllo della skill di essere eseguiti senza una richiesta di approvazione a ogni audit.
Tutto il resto relativo all'installazione è in INSTALLATION.md, l'unico riferimento per i meccanismi di installazione: installazioni manuali file-per-file (a livello globale e di progetto), specifiche per Windows, hook Post-Agent, l'allowlist dei permessi, verifica dell'installazione, aggiornamento, ancoraggio a un tag di release e disinstallazione.
Dopo l'installazione, la gestione quotidiana funziona tramite linguaggio naturale con Claude — install safer-dependencies (riesecuzione / modifica hook), show safer-dependencies stats, check safer-dependencies setup — oppure il menu /safer-dependencies. Anche l'aggiornamento avviene in sessione: /safer-dependencies update applica l'ultima release (update --check per una prova a secco, update --rollback per annullare); consulta INSTALLATION.md per il modello di fiducia.
Nota sulla piattaforma: sono supportati macOS, Linux e Windows. Windows richiede Git for Windows (fornisce bash) e Python 3 nel
PATH— non è richiesto WSL. I test pratici finora si sono concentrati su macOS e Windows; il supporto Linux è verificato dalla matrice CI automatica.
Due aspetti sono configurabili dopo l'installazione:
npm audit / bundle audit e gli script resolver della skill stessa) così gli audit vengono eseguiti senza una richiesta di approvazione ogni volta; curl non viene mai pre-approvato e npm view / pip-audit sono opt-in tramite il profilo Convenience. L'installer interattivo scrive per te le voci principali; le installazioni manuali aggiungono l'intero blocco a mano. Blocco completo e motivazione: INSTALLATION.md → Allowlist dei permessi.off/warn/block per ogni tipo di controllo, configurabili con /safer-dependencies config e salvati in ~/.config/safer-dependencies/config.toml. Schema e semantica dei livelli: .Ogni controllo viene registrato in ~/.claude/safer-dependencies-audit-YYYY-MM.log (un file per mese di calendario, dove YYYY-MM è l'anno-mese UTC) come una singola riga JSON. È possibile sostituire il percorso completo con la variabile d'ambiente SAFE_DEP_AUDIT_LOG (quando impostata, il suffisso della data non viene aggiunto). I file vengono anche ruotati in base alla dimensione quando superano SAFE_DEP_LOG_MAX_BYTES (default 10 MiB; impostare a 0 per disabilitare). Imposta SAFE_DEP_MODEL per sovrascrivere il valore del modello scritto in source.model in ogni voce — utile per confronti A/B tra versioni del modello.
Tutte e cinque le modalità aggiungono allo stesso file. Ogni voce contiene un blocco source (schema 2.2) che identifica quale componente l'ha scritta:
source.model registra il modello Claude Code attivo nella sessione (ad es. "claude-sonnet-4-6"). Presente nello schema 2.1+; le voci scritte da installazioni precedenti omettono il campo. Il comando stats degrada senza problemi a "unknown" quando è assente.
Filtra per source.component con 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
Per un'analisi più semplice, chiedi a Claude le statistiche di utilizzo invece di analizzare manualmente i log:```
"Show safer-dependencies stats for the last month"
Questo fornisce riepiloghi leggibili dall'uomo dell'attività, dell'impatto sulla sicurezza e delle metriche di prestazione estratti da questi log di audit.
Forme delle voci (schema 2.2). Tre forme distinte condividono la stessa intestazione ts / schema / source:
Voci di audit: la modalità Intercept esegue l'intera pipeline (provenienza, età della versione, OSV, abbandonati/obsoleti, typosquat, firme), quindi tutti gli array possono essere popolati. La modalità Pre-Install esegue al momento solo OSV, quindi abandoned / stale / typosquat / signatures sono sempre vuoti. Il dispatch Post-Install (audit del lockfile) scrive sotto shim.posttooluse con findings popolato dalle stringhe WARNING: degli auditor del lockfile. L'array notes contiene segnali informativi NOTE: (ad es. manifest-skipped-because-unpinned).
Lo schema 2.2 ha aggiunto — in modo additivo — quattro campi alle voci di audit lockfile: lockfile, manifest_ref, relation_summary (una classificazione diretto/transitivo/sconosciuto di ogni pacchetto segnalato rispetto al manifest correlato), e un blocco policy che registra il livello transitive in vigore. L'incremento di versione è retrocompatibile: i lettori delle voci 2.1 tollerano i nuovi campi, e il campo source.model rimane presente dalla 2.1 in poi.```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]"]
}
Esempio di modalità Pre-Install (hook Bash, pin vulnerabile negato):```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]"]
}
Esempio della modalità fail-open (hook Bash post-installazione chiamato senza shim adiacente — installazione danneggiata):```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" } }
Una voce fail-open indica: "questo hook è stato attivato ma è uscito in anticipo senza eseguire l'audit perché mancava un prerequisito." Usa il filtro jq qui sopra (`select(.source.mode == "fail_open")`) per far emergere ogni evento silenzioso di perdita di protezione nel log.
Quando lo shim viene eseguito in modalità dry-run (`SAFE_DEP_DRY_RUN=1`), le voci includono anche `"mode": "dry_run"` così che l'analisi a posteriori possa filtrare le sole invocazioni di audit.
## Requisiti
- Python 3.9+ (gli hook lo verificano e vanno in fail-open su interpreti più vecchi)
- `curl` (per le chiamate API del registry e i controlli delle vulnerabilità OSV)
- Strumenti dell'ecosistema (opzionali, la skill ripiega sull'API OSV se mancano):
- `npm` per i pacchetti npm
- `pip-audit` per i pacchetti Python
- `bundle` per i pacchetti Ruby
- `dependency-check` per i pacchetti Java
## FAQ
La logica delle decisioni progettuali (perché `PostToolUse` invece di `PreToolUse`, perché le firme non vengono verificate, perché gli script e lo shim sono duplicati, le insidie del caricamento delle skill, ecc.) è documentata in [`FAQ.md`](https://github.com/robert-auger/safer-dependencies/blob/HEAD/FAQ.md).
CLEAN:hookSpecificOutput.additionalContextREGRESSION:MAJOR-UPDATE-CONFIRM:ls, cat, git status, …), controlla i manifesti
modificati di recente. Questo è l'unico fallback per le modifiche ai manifesti
effettuate tramite sed -i, jq o uno script — quelle bypassano lo strumento
Write/Edit su cui si aggancia la Intercept Mode.pip install /
pip install -r requirements.txt non scrive alcun file di lock, quindi Scan A
non vede mai l'albero risolto. Dopo un'installazione di tipo pip, Scan C richiama
la stessa pip con un list --format=json di sola lettura e verifica tramite OSV
l'intero ambiente risolto (diretto + transitivo).hookSpecificOutput all'agente padreskills/references/configuration.md| Level | Significato | Esempio |
|---|
| CRITICAL | Fermati e chiedi all'utente | Typosquat rilevato, firma manomessa |
| HIGH | Avvisa e prosegui | CVE noto, pacchetto con meno di 30 giorni |
| MEDIUM | Avvisa e prosegui | Versione < 7 giorni, firma mancante |
| LOW | Avvisa e prosegui | Gem Ruby non firmata (previsto) |
source.component | Scritto da | Trigger |
|---|
shim.posttooluse | shim.sh | Scrittura di manifest o lockfile (Intercept Mode, dispatch post-installazione) |
shim.install_error | shim.sh | Errore di preflight dell'installazione dello shim |
bash.pretooluse | pretooluse-bash.sh | Comando di installazione Bash (Pre-Install Mode) |
bash.posttooluse | posttooluse-bash.sh | L'hook Bash Post-Install stesso, quando va in fail-open prima di raggiungere lo shim |
agent.pretooluse | pretooluse-agent.sh | Riservato agli eventi fail-open Pre-Agent (l'hook stesso è attualmente silenzioso in caso di successo) |
agent.posttooluse | posttooluse-agent.sh | Eventi fail-open dell'hook Post-Agent (ad es. shim mancante, python_missing) |
manual.skill | Claude in esecuzione in Normal Mode | Audit manuale invocato inline |
| Forma | Quando viene scritta | Campi distintivi |
|---|
| Voce di audit | Audit di manifest / lockfile / bash-install | file, ecosystem, checked, findings, abandoned, stale, typosquat, unknown, signatures, notes, clean |
| Voce di errore di installazione | Errore di installazione preflight dello shim (componente shim.install_error) | install_error, shim_dir, scripts_dir |
| Voce fail-open | Qualsiasi punto di ingresso dell'hook esce anticipatamente a causa di helper_missing / shim_missing / python_missing. source.mode è "fail_open" | fail_open: { reason, detail? } |