npm supply chain defense checklist: how to block risky dependency changes in CI
A practical checklist to reduce npm supply chain risk by treating dependency diffs as security events. Focus on new dependencies, install scripts, lockfile discipline, and incident first moves.
Table of Contents
- Conclusion
- Explanation
- Practical Guide
- Step 1 (baseline): make builds reproducible
- Step 2: define the two hard stops
- Step 3: standardize dependency change review
- Step 4: batch upgrades (reduce churn)
- Step 5: incident first moves (when compromise is suspected)
- Pitfalls
- Checklist
- FAQ
- Q1. Isn’t this too strict for fast shipping?
- Q2. Do UUIDs or code review help here?
- Q3. What’s the minimum control if I do only one thing?
- Internal links
- References
How do you defend against npm supply chain attacks in a small team?
Conclusion
You don’t need a SOC to reduce most supply chain risk. You need CI gates that treat dependency graph changes as security events.
The highest-signal controls are:
- block or require approval for new dependencies
- block or require approval for install scripts (
preinstall/install/postinstall) - always commit lockfiles and use
npm ci
If you ship faster with AI assistance, these gates matter more, not less.
Explanation
Many incidents bypass application code review:
- maintainer account compromised
- main package code looks fine
- a new dependency is added
- payload runs via install scripts
That’s why “search the repo for malware strings” often fails. The actionable signal is the diff of your dependency graph.
Practical Guide
Step 1 (baseline): make builds reproducible
- commit your lockfile (
package-lock.json/pnpm-lock.yaml/yarn.lock) - use
npm ciin CI (avoid resolution drift)
Decision rule:
- If the lockfile is not committed, you cannot prove what actually ran.
Step 2: define the two hard stops
Hard stop #1: new dependency added
- new direct dependency in
package.json - new package introduced in lockfile
Hard stop #2: install scripts
preinstallinstallpostinstall
Policy:
- if a new dependency has install scripts, require explicit approval
Step 3: standardize dependency change review
Keep the review surface small:
package.json- lockfile
Then enforce via CI:
- failing checks if new deps are introduced without approval
- optional allowlist for known-safe packages
Step 4: batch upgrades (reduce churn)
- bundle upgrades into a weekly PR
- treat emergency patches as explicit exceptions
Why it matters:
- easier to review and attribute changes
- faster incident response
Step 5: incident first moves (when compromise is suspected)
- pin/rollback to a known-good version
- assume CI runners may be affected
- rotate credentials if secrets were present
Decision rule:
- If the build environment had secrets, assume exposure until proven otherwise.
Pitfalls
- “The main dependency looks clean” (payload is often in a new transitive dep)
- reviewing only code diffs, not lockfile diffs
- allowing install scripts by default
- letting dependency upgrades scatter across many PRs
Checklist
- [ ] Lockfile is committed
- [ ] CI uses
npm ci(or equivalent) for reproducible installs - [ ] CI fails when a new direct dependency is added
- [ ] CI fails when a new package appears in the lockfile
- [ ] New deps with install scripts require explicit approval
- [ ] Install script policy is documented (
preinstall/install/postinstall) - [ ] Dependency upgrades are batched (weekly) by default
- [ ] Emergency patch process exists (explicit exception path)
- [ ] Incident playbook exists (pin/rollback, runner risk, secret rotation)
- [ ] PR template includes “dependency change” section
- [ ] Logs/artifacts allow post-incident forensics (what version ran)
FAQ
Q1. Isn’t this too strict for fast shipping?
No. The gates target rare, high-risk events (new deps, install scripts). Fast shipping without gates is how incidents slip in.
Q2. Do UUIDs or code review help here?
Code review helps, but supply chain payloads often enter via transitive dependency changes and install-time execution. You must review the graph diff.
Q3. What’s the minimum control if I do only one thing?
Fail CI on “new dependency added”. Make every new dependency an explicit review decision.
Internal links
- Parent hub: AI development: start here
- Related:
References
- StepSecurity (axios write-up): https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan
- Socket (dependency-diff angle): https://socket.dev/blog/axios-npm-package-compromised
- Snyk (remediation): https://snyk.io/blog/axios-npm-package-compromised-supply-chain-attack-delivers-cross-platform/
Popular
- 1Permit2 explained (Web3): why approvals changed and how to use it safely (checklist)
- 2Read wallet signing screens (Web3): a 30-second checklist to avoid permission traps
- 3Spec-to-implementation prompt template (AI development): how to stop the model from guessing
- 4Revoke token approvals on EVM: how to audit allowances safely (checklist)
- 5Clarifying questions checklist (AI development): what to ask before you let an LLM build