One Liner
2026-06-05 10:20
Harden JavaScript package installs by blocking lifecycle scripts and adding a release-age cooldown.
- block lifecycle scripts to reduce dependency-install attack surface
- add a minimum release age so fresh malicious releases do not install immediately
Requirement: npm >= 11.10
npm install -g npm@latest
npm config set ignore-scripts truenpm config set min-release-age 7
npm config ls -l | grep -E "ignore-scripts|min-release-age"
~/.npmrc
- project lifecycle hooks are also disabled
- run needed scripts explicitly
- use
npm rebuild <pkg>for one package if needed - urgent install escape hatch:
npm install <pkg> --min-release-age=0
Requirement: pnpm >= 10.16
Already blocked by default in pnpm 10+.
pnpm config set --global minimumReleaseAge 10080
pnpm config get minimumReleaseAge
~/Library/Preferences/pnpm/rc
minimumReleaseAgeExclude- supports globs like
@myorg/*
Requirement: bun >= 1.3.8
Already blocked by default.
- add to
~/.bunfig.toml [install]minimumReleaseAge = 604800
minimumReleaseAgeExcludes = ["<pkg>"]
Machine-wide supply-chain hardening for npm, pnpm, and Bun.
Apply two protections to all three package managers (user-level, not per-project):- Disable/block dependency lifecycle scripts (postinstall attack vector — Shai-Hulud, qix/chalk compromises)- Minimum release age cooldown of 7 days (malicious releases are typically yanked within hours/days)
Units differ per manager: npm = DAYS, pnpm = MINUTES, Bun = SECONDS.
1. npm (requires npm >= 11.10)Upgrade if older:
npm install -g npm@latest
Apply:
npm config set ignore-scripts truenpm config set min-release-age 7
Verify:
npm config ls -l | grep -E "ignore-scripts|min-release-age"# ignore-scripts = true# min-release-age resolves to a `before` date (7 days ago from now)
Writes to ~/.npmrc.
Caveatsignore-scripts also disables the project's own npm lifecycle hooks (pre/postbuild, prepare, etc.) — run those scripts explicitly where needed.Native deps (sharp, esbuild, lightningcss) still work — they ship prebuilt binaries via optionalDependencies. If a package breaks: npm rebuild <pkg> runs only that package's scripts.Urgent fresh install: npm install <pkg> --min-release-age=0If npm was bundled with Homebrew node, brew upgrade node may downgrade npm — re-upgrade after.
2. pnpm (requires >= 10.16)Lifecycle scriptsAlready blocked by default since pnpm 10.0.0 — nothing to do.Per-project allowlist when needed: pnpm.onlyBuiltDependencies in package.json (v10) or allowBuilds map (v11). Never set dangerouslyAllowAllBuilds.
Cooldown (7 days = 10080 minutes)pnpm config set --global minimumReleaseAge 10080
Verify:
pnpm config get minimumReleaseAge# 10080
Writes minimum-release-age=10080 to the global rc (macOS: ~/Library/Preferences/pnpm/rc, Linux: ~/.config/pnpm/rc).
Escape hatchesminimumReleaseAgeExclude list (supports globs like @myorg/*).pnpm 11 enables 1440-min cooldown by default + adds strictDepBuilds, trustPolicy: no-downgrade, blockExoticSubdeps — worth upgrading when convenient.
3. Bun (requires >= 1.3.8 — older 1.3.x had a bug ignoring global bunfig)Lifecycle scriptsAlready blocked by default (built-in allowlist of ~vetted packages) — nothing to do.Per-project trust when needed: bun pm trust <pkg> → adds to trustedDependencies in package.json.
Cooldown (7 days = 604800 seconds)
Create/append ~/.bunfig.toml:
[install]minimumReleaseAge = 604800
Escape hatch[install]minimumReleaseAgeExcludes = ["<pkg>"]
Live verificationPick any package version published <7 days ago and confirm install is blocked:
V=$(npm view electron-to-chromium version)npm view electron-to-chromium time --json | grep "$V" # confirm publish date is recent
mkdir -p /tmp/cooldown-test && cd /tmp/cooldown-testecho '{"name":"t","version":"0.0.0"}' > package.json
bun add "electron-to-chromium@$V" # expect: blocked by minimum-release-agepnpm add "electron-to-chromium@$V" # expect: error suggesting minimumReleaseAgeExclude
cd / && rm -rf /tmp/cooldown-test
If the latest version happens to be >7 days old, pick another fast-moving package (e.g. caniuse-lite).
SummaryManager | Version req | Scripts setting | Cooldown setting | Config locationnpm | >= 11.10 | ignore-scripts=true | min-release-age=7 (days) | ~/.npmrcpnpm | >= 10.16 | default blocked (v10+) | minimumReleaseAge=10080 (minutes) | global rcBun | >= 1.3.8 | default blocked | minimumReleaseAge=604800 (seconds) | ~/.bunfig.toml1 Linked mention
- Tech
…Machine Learning Specialization Notes Claude Code RTK and Caveman Setup Supply-chain Hardening for npm pnpm and Bun Related indexes Atlas Knowledge Crypto Business