Guard your dependencies against supply chain attacks.

Prevent the next npm supply chain compromise from impacting you. One command to scan and fix npm, pnpm, yarn, bun, aube, uv, pip, and poetry configs for security best practices. Zero dependencies. MIT.

Install

brew install depsguard

Homebrew (in homebrew-core – no tap needed). Works on Apple Silicon and Intel. Update later with brew upgrade depsguard.

Direct binaries · Full install guide

How to use

  1. Install – pick your platform above.
  2. Run depsguard in your terminal to launch the interactive TUI. It scans your system and shows a table of findings. Press any key to continue to the fix selector. Repo-level config discovery starts from the current directory and searches downward. Use depsguard scan for a read-only report, or depsguard --no-search to skip the recursive file search and only check user-level configs.
    Note: some settings require a minimum version. If your version is too old you'll see:
    ℹ min-release-age – requires npm ≥ 11.10 (have 10.2.0)
    Upgrade with npm install -g npm@latest and re-run.
  3. Navigate & select – use to move through the list (^u^d to page). Press Space to toggle a fix on or off. Use quick-filter keys to bulk-select by file: a all, n .npmrc, u uv.toml, etc. – press once to select, again to deselect, a third time to clear the filter. Press f to show only currently selected fixes.
  4. Preview – press d to see a diff of what will change before you commit to anything.
  5. Apply – press Enter to apply the selected fixes. A timestamped backup is created before any file is written.
  6. Rescan – DepsGuard automatically reruns the scan after applying, so you can verify everything is green.
  7. Restore – run depsguard restore at any time to roll back from the backup list. Press q or Esc to quit.

Full documentation, config file locations, and troubleshooting tips are in the README.

Why this exists

Software supply chain attacks are increasing. On March 31, 2026, a compromised maintainer account was used to publish malicious versions of axios. The bad versions were live for ~3 hours before removal. Similar short-lived attacks hit ua-parser-js, colors, and node-ipc. Bigger campaigns followed: the self-replicating Shai-Hulud worm spread through hundreds of npm packages in 2025, and in May 2026 attackers poisoned dozens of TanStack packages through a compromised CI pipeline. The pattern is the same: an attacker publishes a poisoned version, and every npm install that runs before it's caught pulls it in.

Many modern package managers now ship with built-in defenses, and some are on by default: pnpm 11 enables a 24-hour cooldown and blocks exotic transitive dependencies, and npm v12 (expected in 2026) will block install scripts and git or remote-URL dependencies by default. But the defaults vary by version and are often weaker than they should be, so DepsGuard checks what is actually enabled and helps you turn on, or strengthen, the rest.

Supported settings

Manager Config file Setting What it does Docs
npm .npmrc min-release-age=7 Delay new versions by 7 days (npm ≥ 11.10)
npm / pnpm .npmrc ignore-scripts=true Block malicious install scripts (npm honors this in .npmrc; pnpm ≥ 11 reads it from pnpm-workspace.yaml / global config.yaml)
pnpm .npmrc minimum-release-age=10080 Delay new versions by 7 days (in minutes) (pnpm 10.16–10.x; pnpm ≥ 11 ignores .npmrc; use pnpm-workspace.yaml)
pnpm rc (pnpm ≤ 10; pnpm ≥ 11 uses config.yaml with camelCase keys) ignore-scripts=true Block malicious install scripts
minimum-release-age=10080 Delay new versions by 7 days (pnpm ≥ 10.16)
block-exotic-subdeps=true Block untrusted transitive deps (pnpm ≥ 10.26)
trust-policy=no-downgrade Block provenance downgrades (pnpm ≥ 10.21)
strict-dep-builds=true Fail on unreviewed build scripts (pnpm ≥ 10.3)
pnpm pnpm-workspace.yaml minimumReleaseAge: 10080 Delay new versions by 7 days (in minutes) (pnpm ≥ 10.16)
strictDepBuilds: true Fail on unreviewed build scripts (pnpm ≥ 10.3)
trustPolicy: "no-downgrade" Block provenance downgrades (pnpm ≥ 10.21)
blockExoticSubdeps: true Block untrusted transitive deps (pnpm ≥ 10.26)
ignoreScripts: true Block malicious install scripts (pnpm ≥ 10.16)
pnpm config.yaml (global; pnpm ≥ 11) minimumReleaseAge: 10080 Delay new versions by 7 days (in minutes)
blockExoticSubdeps: true Block untrusted transitive deps
trustPolicy: "no-downgrade" Block provenance downgrades
strictDepBuilds: true Fail on unreviewed build scripts
ignoreScripts: true Block malicious install scripts
Yarn .yarnrc.yml npmMinimalAgeGate: "7d" Delay new versions by 7 days (yarn ≥ 4.10)
bun .bunfig.toml install.minimumReleaseAge = 604800 Delay new versions by 7 days (in seconds) (bun ≥ 1.3)
aube .npmrc minimumReleaseAge=10080 Delay new versions by 7 days (in minutes)
uv uv.toml exclude-newer = "7 days" Delay new versions by 7 days (uv ≥ 0.9.17)
pip pip.conf [install] uploaded-prior-to = P7D Delay new versions by 7 days (pip ≥ 26.1)
poetry config.toml [solver] min-release-age = 7 Delay new versions by 7 days (poetry ≥ 2.4)
Renovate renovate.json "minimumReleaseAge": "7 days" Delay dependency update PRs
Dependabot dependabot.yml cooldown.default-days: 7 Delay dependency update PRs

User-level config locations

Manager macOS Linux Windows $XDG_CONFIG_HOME
npm ~/.npmrc n/a
pnpm ~/.npmrc (shared with npm) n/a
aube ~/.npmrc (shared with npm) n/a
pnpm global, ≤ 10 ~/Library/Preferences/pnpm/rc ~/.config/pnpm/rc %LOCALAPPDATA%\pnpm\config\rc $XDG_CONFIG_HOME/pnpm/rc
pnpm global, ≥ 11 ~/Library/Preferences/pnpm/config.yaml ~/.config/pnpm/config.yaml %LOCALAPPDATA%\pnpm\config\config.yaml $XDG_CONFIG_HOME/pnpm/config.yaml
Yarn ~/.yarnrc.yml n/a
bun ~/.bunfig.toml $XDG_CONFIG_HOME/.bunfig.toml *
uv ~/.config/uv/uv.toml %APPDATA%\uv\uv.toml $XDG_CONFIG_HOME/uv/uv.toml *
pip ~/Library/Application Support/pip/pip.conf ~/.config/pip/pip.conf %APPDATA%\pip\pip.ini $XDG_CONFIG_HOME/pip/pip.conf *
poetry ~/Library/Application Support/pypoetry/config.toml ~/.config/pypoetry/config.toml %APPDATA%\pypoetry\config.toml $XDG_CONFIG_HOME/pypoetry/config.toml *

* When $XDG_CONFIG_HOME is set, DepsGuard prefers the XDG path. For bun, each existing config file is scanned independently. For pip, uv, and poetry, it resolves a single effective config: pip/poetry use the highest-precedence file that sets the value, and uv reads the XDG file in place of ~/.config (it does not merge both). If no config exists, the XDG path is used as the default for new fixes.

Urgent security fix

If the patched version is newer than your cooldown window, add a narrow exception, install the fix, and then remove the exception.

Prefer a package-specific exception over lowering the global cooldown. That keeps the delay in place for every other dependency.

Manager How to bypass the cooldown
npm npm install <pkg>@<ver> --min-release-age=0
pnpm Add an entry to minimumReleaseAgeExclude in pnpm-workspace.yaml, run pnpm add <pkg>@<ver>, then remove the entry.
Excluding by package name works on pnpm 10.16+; pinning a specific version (<pkg>@<ver>) additionally requires pnpm 10.19+. pnpm has no documented CLI override for minimumReleaseAge.
Yarn Add <pkg> (or a glob) to npmPreapprovedPackages in .yarnrc.yml, or run YARN_NPM_MINIMAL_AGE_GATE=0s yarn up <pkg>@<ver> for one command.
npmPreapprovedPackages exempts matches from all Yarn package gates, not only the age gate.
bun Add <pkg> to install.minimumReleaseAgeExcludes in a repo-level bunfig.toml or user-level ~/.bunfig.toml, or run bun add <pkg>@<ver> --minimum-release-age 0.
aube Add <pkg> to minimumReleaseAgeExclude in .npmrc, or set AUBE_MINIMUM_RELEASE_AGE=0 (or npm_config_minimum_release_age=0) for a single install.
uv Add "<pkg>" = false to exclude-newer-package in uv.toml or pyproject.toml, run uv add <pkg>==<ver>, then remove the entry.
exclude-newer-package is a separate per-package override of the global exclude-newer cutoff. uv's CLI accepts --exclude-newer-package PACKAGE=DATE but not PACKAGE=false.
pip Run pip install <pkg>==<ver> --uploaded-prior-to=P0D for one install.
P0D disables the cooldown only for that command; pip has no per-package exclusion in config.
poetry Add <pkg> to solver.min-release-age-exclude (comma-separated) in poetry.toml/config.toml, run poetry add <pkg>@<ver>, then remove the entry.
solver.min-release-age-exclude-source exempts every package from a named index instead.
Renovate Security updates already bypass minimumReleaseAge. For a version update, add a packageRules entry with matchPackageNames: ["<pkg>"] and minimumReleaseAge: null.
Dependabot Security updates already bypass cooldown. For a version update, add <pkg> to cooldown.exclude.

Before you bypass the cooldown

  1. Check whether the CVE actually affects your usage.
  2. Check whether a known-good older version is already available. A rollback may be safer.
  3. Remove temporary exceptions after the upgrade.

Guides & deep dives

Detailed explanations of each hardening setting and the supply chain attacks they defend against.

FAQ

What is DepsGuard?

DepsGuard is a free, open-source command-line tool that scans your npm, pnpm, yarn, bun, aube, uv, pip, and poetry configuration and turns on the built-in security settings that protect against supply chain attacks, such as install-script blocking and version cooldowns. It never runs installs; it only edits config files you approve, and it writes a backup before any change.

Will this protect against all supply chain attacks?

No. DepsGuard focuses on one specific layer: delaying the adoption of brand-new package versions and disabling risky install scripts. This buys you time when an attacker publishes a poisoned release, because your package manager won't pull it in immediately. It does not protect against compromised packages that go undetected for weeks, typosquatting, or attacks that don't involve publishing a new version.

How would this have helped during the axios compromise?

On March 31, 2026, a compromised maintainer account published malicious versions of axios. The bad versions were live for roughly 3 hours before being removed from the registry. If your package manager was configured with a 7-day minimum release age (like min-release-age=7 in .npmrc), it would have refused to download the new version during that window. The same logic applies to incidents like ua-parser-js (compromised for ~4 hours in Oct 2021) and node-ipc (caught within days in Mar 2022) – in each case, the poisoned version was removed well within a 7-day quarantine period. Note: this would not have helped with attacks like event-stream, where the malicious code went undetected for months.

Why can this protect me against future attacks?

Many supply chain attacks follow the same pattern: an attacker publishes a poisoned package version and relies on automated installs pulling it in before anyone notices. Registry security teams, community reports, and automated scanners often catch and remove these within hours or days. A minimum release age means your package manager won't pull in a version that hasn't been publicly available for at least 7 days, giving that detection window time to work. This is effective against fast-response attacks (like axios, ua-parser-js, node-ipc) but does not help if malicious code goes undetected for longer than the quarantine period.

What's the difference between this and Software Composition Analysis (SCA)?

SCA tools (like npm audit, OWASP dep-scan, Grype, Arnica, or Snyk) scan your existing dependencies for known vulnerabilities after you've already installed them. DepsGuard works before installation – it configures your package manager to avoid pulling in newly published versions until they've had time to be vetted. They're complementary: SCA finds known CVEs in your current lockfile, DepsGuard reduces the chance that a freshly poisoned version gets installed in the first place.

What else can I do to protect myself?

DepsGuard covers package manager config, but there's more you can do:

  • Pin GitHub Actions by commit SHA (uses: actions/checkout@a81bbb...) instead of a tag like @v4. Tags can be moved to point at different commits; SHAs can't.
  • Use npm ci, pnpm install --frozen-lockfile, or yarn install --immutable in CI. These commands fail if the lockfile is out of date, so CI never resolves new versions on its own.
  • Don't auto-merge Dependabot or Renovate PRs without reviewing changelogs, diffs, and provenance.
  • Audit your dependency tree periodically with npm ls or pnpm why. Fewer dependencies means fewer places an attacker can hide.

What should I do if I need to patch an urgent CVE?

If the patched version is newer than your cooldown window, your package manager will refuse to install it by default – that's the cooldown doing its job. To get the fix in, add a narrow, package-specific exception, install the patched version, then remove the exception so the delay stays in place for every other dependency. Prefer a per-package override to lowering the global cooldown.

Before you bypass the cooldown: confirm the CVE actually affects how you use the package, and check whether a known-good older version is already available (a rollback may be safer). See the Urgent security fix section for the exact per-manager commands (npm, pnpm, yarn, bun, aube, uv, pip, poetry, Renovate, Dependabot). Note that Renovate and Dependabot security updates already bypass the cooldown automatically.

Is this free?

Yes. DepsGuard is free and open source under the MIT license.

Can I use this commercially?

Yes. The MIT license permits commercial use, modification, and distribution with no restrictions.

Who made this?

Arnica, an application security company based in Atlanta. DepsGuard is a free, open-source tool we built to help anyone harden their package manager config.

I found a bug. What should I do?

Open an issue on GitHub. For security vulnerabilities, please use GitHub Security Advisories to report privately.

See also

Dependency Cooldowns (cooldowns.dev) – a reference guide and companion shell helper (cooldowns.sh) focused specifically on minimum-release-age cooldowns. It complements DepsGuard: cooldowns.dev covers a broader set of ecosystems on the cooldown axis (pip, uv, npm, pnpm, Yarn, Bun, Deno, Cargo), while DepsGuard covers npm/pnpm/yarn/bun/aube/uv/pip/poetry plus Renovate and Dependabot and adds other hardening settings (ignore-scripts, block-exotic-subdeps, trust-policy, strict-dep-builds) with an interactive TUI, diff preview, and backup/restore.

Help & feedback

Report a bug or request a feature Report a security vulnerability