depcurfew v1.6.1
On this page

Start with npm, pnpm, Yarn (Berry), Bun and Deno

What the README and the knowledge base say about these tools, on one page.

Five-minute start

  1. npx depcurfew doctor works before init: without depcurfew.json it compares the repository with the policy init would write and shows, as notes in a block of their own, what init and apply would change, for example a package manager that installs new versions without a release-age delay, with the settings apply would write for it. These notes never make it fail.
  2. npx depcurfew init writes depcurfew.json with the default policy below and lists the tools it detected. When the repository already sets a longer release-age delay for one of them, cooldown.minimum keeps the longest one, and init says where it found it.
  3. npx depcurfew explain shows what it detected and what the policy means for each tool.
  4. npx depcurfew apply --dry-run prints the changes as a diff, without writing anything.
  5. npx depcurfew apply writes them. Run it again whenever depcurfew.json changes; a second run with the same policy changes nothing.
  6. npx depcurfew doctor reports configuration that silently does not work and drift from the policy, and exits with 1 when it finds an error or, with the "doctor": { "failOn": "warning" } that init writes, a warning.
  7. Add the GitHub Action so that doctor runs on every push and reports to code scanning.

The default policy:

{
  "$schema": "https://unpkg.com/depcurfew/schema.json",
  "version": 1,
  "cooldown": {
    "minimum": "3d",
    "exclude": [],
    "securityUpdates": "bypass"
  },
  "installScripts": {
    "default": "deny",
    "allow": [],
    "deny": []
  },
  "sources": {
    "git": "deny",
    "remoteTarball": "deny",
    "file": "allow",
    "directory": "allow"
  },
  "targets": "auto",
  "doctor": {
    "failOn": "warning"
  }
}

Supported tools

ToolRelease-age delayExceptionsInstall-script allow-list (Python: packages built from source; Composer: plugins)Dependency sourcesVerified
npmmin-release-age in .npmrc (days), since 11.10.0min-release-age-exclude, since 11.17.0allowScripts in package.jsongit: allow-git
remote tarball: allow-remote
local tarball: allow-file
local directory: allow-directory
2026-10-28 – 2026-11-11
pnpmminimumReleaseAge in pnpm-workspace.yaml (minutes), since 10.16.0minimumReleaseAgeExclude, since 10.16.0allowBuilds in pnpm-workspace.yamlgit: blockExoticSubdeps
remote tarball: blockExoticSubdeps
2026-10-28 – 2026-11-09
Yarn (Berry)npmMinimalAgeGate in .yarnrc.yml (minutes), since 4.10.2npmPreapprovedPackages, since 4.10.0dependenciesMeta.<package>.built in package.jsongit: approvedGitRepositories2026-10-28 – 2026-11-03
Buninstall.minimumReleaseAge in bunfig.toml (seconds), since 1.3.0install.minimumReleaseAgeExcludes, since 1.3.0trustedDependencies in package.jsonnone2026-10-28 – 2026-11-11
DenominimumDependencyAge in deno.json (minutes) or min-release-age in .npmrc (days), since 2.5.5 / 2.6.0 ⚠️minimumDependencyAge.exclude, since 2.5.5allowScripts in deno.jsonnone2026-10-28 – 2026-11-11

⚠️ official sources disagree (depcurfew takes the safer reading) · ❓ official sources are incomplete. Every value with its source: docs/knowledge.md.

Protecting the whole machine

ToolUser fileSettings apply --user writes (versions that read them there)Needs the exact version
npmLinux, macOS: ~/.npmrc
Windows: %HOME%\.npmrc (when it is an absolute path), else ~\.npmrc
min-release-age (11.10.0+), min-release-age-exclude (11.17.0+), strict-allow-scripts (11.16.0+), allow-scripts (11.16.0+), allow-git (11.10.0+), allow-remote (11.15.0+), allow-file (11.15.0+), allow-directory (11.15.0+)no
pnpmLinux: $XDG_CONFIG_HOME/pnpm/rc, else ~/.config/pnpm/rc
macOS: $XDG_CONFIG_HOME/pnpm/rc, else ~/Library/Preferences/pnpm/rc
Windows: %XDG_CONFIG_HOME%\pnpm\rc, else %LOCALAPPDATA%\pnpm\config\rc, else ~\.config\pnpm\rc
11.0.0+: Linux: $XDG_CONFIG_HOME/pnpm/config.yaml, else ~/.config/pnpm/config.yaml
macOS: $XDG_CONFIG_HOME/pnpm/config.yaml, else ~/Library/Preferences/pnpm/config.yaml
Windows: %XDG_CONFIG_HOME%\pnpm\config.yaml, else %LOCALAPPDATA%\pnpm\config\config.yaml, else ~\.config\pnpm\config.yaml
minimum-release-age (10.16.0–11.0.0), minimum-release-age-exclude (10.16.0–11.0.0), only-built-dependencies (10.0.0–11.0.0), strict-dep-builds (10.3.0–11.0.0), block-exotic-subdeps (10.26.0–11.0.0), minimumReleaseAge (11.0.0+), minimumReleaseAgeExclude (11.0.0+), minimumReleaseAgeStrict (11.0.0+), strictDepBuilds (11.0.7+), blockExoticSubdeps (11.0.0–12.0.0)yes
Yarn (Berry)Linux, macOS, Windows: ~/.yarnrc.ymlnpmMinimalAgeGate (4.10.2+), npmPreapprovedPackages (4.10.0+), enableScripts (4.0.0+), approvedGitRepositories (4.14.0+)yes
BunLinux, macOS, Windows: $XDG_CONFIG_HOME/.bunfig.toml (when it is set, also to an empty value), else ~/.bunfig.toml
1.4.4+: Linux, macOS, Windows: $XDG_CONFIG_HOME/.bunfig.toml (when it is an absolute path), else ~/.bunfig.toml
install.minimumReleaseAge (1.3.0+), install.minimumReleaseAgeExcludes (1.3.0+)yes
Deno1.45.0+: Linux, macOS, Windows: ~/.npmrcmin-release-age (2.8.0+)no

More: Protecting the whole machine.

doctor rules for these tools

npmrc-overrides-policy

error · An .npmrc file changes a security setting in a way the policy does not see, or is ignored.

Package managers read .npmrc from different places with different priorities. npm ignores the .npmrc of workspace packages and the keys below a [section] header, and a before date in .npmrc takes the place of min-release-age; pnpm 10 applies a root .npmrc value whenever pnpm-workspace.yaml does not set the same setting, which can weaken the policy, and dangerously-allow-all-builds there runs every build script while pnpm-workspace.yaml has no build settings of its own.

Fix: Keep security settings out of .npmrc files that are ignored or that override the policy; set them through depcurfew.json and depcurfew apply.

pnpm-shared-workspace-lockfile

warning · pnpm 10 without a shared lockfile lets a package .npmrc change the release-age delay.

With sharedWorkspaceLockfile: false, pnpm 10 installs every workspace project separately with that project's own .npmrc layered over the workspace settings (read from the pnpm 10 source code), so a setting such as minimum-release-age=0 in a package .npmrc applies to that package.

Fix: Remove security settings from package .npmrc files, or keep the default shared lockfile.

pnpm-config-unverifiable

warning · pnpm loads a pnpmfile or a config-dependency plugin that can change every setting, takes a security setting from a config dependency, or stops at include in pnpm-workspace.yaml.

The updateConfig hook of a pnpmfile (.pnpmfile.mjs, .pnpmfile.cjs, or the files the pnpmfile and globalPnpmfile settings name) and of the pnpmfile pnpm loads by itself from a config dependency named pnpm-plugin-*, @*/pnpm-plugin-* or @pnpm/plugin-* can change every setting after pnpm has read pnpm-workspace.yaml, so the delay and the build settings depcurfew checks may not hold; ignoreScripts does not stop them, ignorePnpmfile does. A plugin the knowledge base knows to set a shorter release-age delay than depcurfew.json is an error. From pnpm 12.15, include in pnpm-workspace.yaml can give a setting to a config dependency, whose values depcurfew cannot read, or to a file outside the directory; and an include pnpm rejects (ERR_PNPM_INVALID_WORKSPACE_INCLUDE, ERR_PNPM_DUPLICATE_SETTING, ERR_PNPM_SETTING_NOT_DELEGATED) makes every pnpm command stop.

Fix: Read what the pnpmfile or plugin changes; set pnpmfile: [] when the project needs no pnpmfile, remove plugins it does not need, keep security settings in pnpm-workspace.yaml or a local file of include, and fix what pnpm rejects in include.

Every rule: doctor rules.

Sources

Every fact behind these tables, with its official source, is in the knowledge base: npm, pnpm, Yarn (Berry), Bun, Deno.