SkillAgentSearch skills...

safer-dependencies

safer-dependencies is a security layer for Claude Code that audits packages before they’re added to your project. It detects and fixes risky dependencies, including CVEs, typosquats, abandoned packages, version-age issues, and adds package-cooldown violations across npm, PyPI, RubyGems, Maven, Go, a…

Install / Use

npx skills add robert-auger/safer-dependencies

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

87/100

Category

Security

Supported Platforms

Claude Code

Safer Dependencies for Claude Code

Automatically checks dependencies that Claude adds through its Write, Edit, and Bash tools, and auto-corrects vulnerable versions in place. Runs provenance, version age, vulnerability, and hash-integrity checks across npm, PyPI, RubyGems, Maven, Go, Rust, and PHP (Composer). Coverage is scoped to writes that go through Claude's tools (Intercept Mode corrects a vulnerable pin after the file lands, within the same tool cycle — not before); see CAPABILITIES.md for exactly what is and isn't covered.

New here? GETTING-STARTED.md takes you from zero to a working install in about five minutes.

Security & privacy: see SECURITY.md (vulnerability disclosure), PRIVACY.md (data egress, no telemetry), and CAPABILITIES.md (what the tool defends against and what it doesn't).

License (source-available — NOT OSI "open source"): Free to use and modify for your own purposes, including for-profit/company internal use and building products you sell. A separate paid license is required only to monetize the software itself — selling it, shipping it inside a product or service that is sold, or offering its functionality to third parties for a fee (including hosted/SaaS/API). Redistribution and derivatives must keep the license and credit this project. See LICENSE (Section 4 for the commercial restriction); commercial-license requests via github.com/robert-auger.

Contents

What it does

When AI coding assistants like Claude add packages to your project, they often pick whatever version sounds right — without checking whether it has known security vulnerabilities, whether the package is still actively maintained, or whether the name is a typo away from a malicious lookalike. safer-dependencies fixes that by sitting between Claude and your manifest files and running security checks automatically, before any unsafe version lands in your code.

When Claude is about to add a package to your project, this skill intercepts and runs 5 checks:

  1. Provenance -- official registry, typosquat detection (npm/PyPI/RubyGems/Maven/crates.io), package age
  2. Version age -- picks the newest stable version published 7+ days ago (cooldown window)
  3. Vulnerability scan -- OSV API, with ecosystem-native tools (npm audit, pip-audit, bundle audit) when available
  4. Hash-pin integrity -- for PyPI requirements.txt lines with --hash=sha256:... pins, the declared hash is validated against PyPI's published hashes; mismatch emits a WARNING
  5. Abandoned & stale packages -- known-abandoned packages (e.g. paperclip, request, pycrypto, github.com/dgrijalva/jwt-go) are hard-blocked immediately with a suggested replacement; packages with no stable release in 2+ years get an advisory STALE: warning. Hard-blocked packages are removed from the manifest and Claude will ask how to proceed; stale-only packages are left in place.

If issues are found, Claude emits warnings and may step back to a safer version. All checks are logged to ~/.claude/safer-dependencies-audit-YYYY-MM.log (one file per calendar month).

How it works

The skill operates in five modes (summarized below; the deepest design rationale lives in skills/safer-dependencies.md):

Normal Mode (Manual)

When Claude is about to write an import, add a package to a manifest, or update a lock file, the skill runs inline in your session:

  1. Queries the package registry for stable versions
  2. Auto-selects the newest version published 7+ days ago (deterministic -- no LLM judgment)
  3. Checks for known vulnerabilities via ecosystem tools and the OSV API
  4. Verifies package signatures where available
  5. Emits warnings if issues are found, pins the exact version
  6. Logs the result to the audit trail

The version selection is handled by standalone Python scripts bundled with the skill, not by the LLM interpreting rules. The command outputs SELECTED: <version> and Claude uses that version exactly.

Intercept Mode (Automatic)

Configure .claude/settings.json with a PostToolUse hook to enable automatic, transparent package verification:

  1. Claude writes a manifest file (e.g. package.json) with the originally-requested version — the file lands on disk
  2. The PostToolUse hook fires immediately after the write completes and invokes safer-dependencies-shim.sh
  3. The shim reads the file, parses declared packages, and runs all security checks (typosquat, abandoned, CVE, staleness, hash-pin)
  4. If corrections are needed, the shim rewrites the manifest in place with safe versions (or removes entries that have no safe version)
  5. The shim emits signals (UPDATED:, BLOCKED:, WARNING:, STALE:, MAJOR-UPDATE-CONFIRM:, REFACTOR-REQUIRED:, REGRESSION:, TYPOSQUAT-CONFIRM:, VERIFY:, CLEAN:) via hookSpecificOutput.additionalContext on stdout. REGRESSION: precedes a MAJOR-UPDATE-CONFIRM: when the audit log shows the same (file, package) was previously corrected to the same safe target — that is, a subagent or stale plan has re-introduced a known-vulnerable version, and the orchestrator should restore the previously-approved version rather than re-deciding the major bump.
  6. Claude receives those signals as a system-reminder and performs follow-up work (find affected imports, run tests, refactor for breaking changes)

Design note — Shape C (post-write corrective): the hook does NOT block writes. Each vulnerable version lands on disk first and is then auto-corrected within the same tool-use cycle. This is a deliberate choice over a PreToolUse blocking design — see FAQ.md for the tradeoffs.

Example signal:

UPDATED: aiohttp 3.8.5 → 3.9.0 (HIGH: 33 CVEs fixed)

The parent agent uses these signals to identify affected code and refactor as needed.

Pre-Install Mode (Bash Hook)

Configure .claude/settings.json with a PreToolUse:Bash hook to enable pre-flight auditing of package-manager install commands. This complements (does not replace) Intercept Mode — together they form a layered defense.

  1. Claude attempts a Bash tool call (e.g. npm install lodash@4.17.20)
  2. The PreToolUse hook fires before the call runs and invokes safer-dependencies-pretooluse-bash.sh
  3. A pure-bash early filter short-circuits non-PM commands in ~115 ms (no Python invocation), so git status / ls / npm test pay negligible cost on the hot path
  4. For recognized package-manager installs (npm/pnpm/yarn install/i/add), the helper tokenizes via shlex, extracts each pkg@version argument, and POSTs to OSV
  5. Any vulnerable concrete pin → the hook returns permissionDecision: "deny" with a per-finding GHSA-id + CVSS + summary, plus a hint to invoke the safer-dependencies skill
  6. The install never runs — no network fetch, no postinstall scripts

Why this exists in addition to Intercept Mode: the post-write shim is blind to Bash. npm install lodash@4.17.20 runs to completion (and postinstall scripts execute) before any audit fires; npm install -g typosquat-pkg writes no project manifest at all. Pre-Install Mode closes those gaps structurally.

Pre-Install Mode only sees what the user typed (pkg@version args on the command line). It can't see the transitive tree the resolver will actually install. Post-Install Mode (below) audits the lockfile once the install completes — the two modes are complementary, not redundant.

Scope: the package-manager CLIs covered here span five ecosystems (npm/pnpm/yarn/bun/npx/deno, pip/pip3/pipx/pipenv/uv/uvx/poetry, gem/bundle, go, cargo), plus Maven via Intercept Mode (Maven dependencies are typically declared in pom.xml/build.gradle, not added via a CLI verb).

Known gap: the Maven CLI does support direct downloads via mvn dependency:get -Dartifact=group:art:version and mvn dependency:copy. This hook does not yet recognize those invocations. If you use them regularly, the existing post-write shim still catches whatever lands in your manifest, but the pre-fetch protection only applies to the ecosystems listed above. Tracked as a follow-up.

Per-ecosystem syntax recognized:

| PM | Verbs | Concrete-pin syntax | |---|---|---| | npm, pnpm, yarn, bun | install, i, add (plus yarn/pnpm dlx, bun x, yarn create) | pkg@1.2.3, @scope/pkg@1.2.3 | | npx | (verbless — package is first positional) | pkg@1.2.3 | | deno | add, install | npm:pkg@1.2.3 (npm-prefixed specs) | | pip, pip3, pipx, pipenv, uv, uvx, poetry | install (pip/pip3/pipx/pipenv) / add (uv/poetry) / verbless (uvx) | pkg==1.2.3 (extras pkg[extra]==X also handled) | | gem, bundle | install (gem) / add | -v 1.2.3, --version 1.2.3, --version=1.2.3 (separate flag) | | go | get, install | pkg@v1.2.3 (must include v prefix per Go modules) | | cargo | add, install | crate@1.2.3 |

Range pins (npm ^4.17, pip >=, poetry ^/~, Go @latest) and unspecified versions pass through to Intercept Mode after install — the post-write shim audits whatever the resolver picks. Auto-rewrite to a safe version is queued as a follow-up.

Failure mode: fail-open. Any error (Python missing, network blip, malformed input) exits 0 with no output, allowing bash to proceed. Intercept Mode still runs after install, so a failed pre-flight degrades gracefully to existing protection.

Example deny:

safer-dependencies pre-flight audit blocked this install.
Vulnerable pinned version(s) detected:
  - lodash@4.17.20 → 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.

Post-Install Mode (Bash Hook)

Configure .claude/settings.json with a PostToolUse:Bash hook to enable post-flight auditing after Bash commands. It runs three independent scans against the command's cwd, each closing a gap the other hooks can't address:

  • Scan A — lockfiles. After a successful install verb (npm install, bundle install, poetry install, uv sync, go mod tidy, etc.), audits freshly-modified lockfiles (package-lock.json, Gemfile.lock, poetry.lock, uv.lock, go.sum, yarn.lock, pnpm-lock.yaml, Pipfile.lock). This closes the transitive-CVE gap Pre-Install can't see: the user typed pkg@version, but the resolver may have pulled in dozens of transitives no one named.
  • Scan B — manifests. After any Bash command not on a read-only denylist (ls, cat, git status, …), audits freshly-modified manifests. This is the only fallback for manifest edits made via sed -i, jq, or a script — those bypass the Write/Edit tool that Intercept Mode hooks on.
  • Scan C — resolved environment. Pla

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars41
CategorySecurity
Updated21d ago
Forks0

Languages

Python

Security Score

85/100

Audited on Aug 31, 2026

1 medium1 info