Part II β The Shield Β· Lesson 3.7
Dependency Security
In one lineYou wrote 5% of the code you ship β the other 95% is your attack surface too.
Where you've seen itThe event-stream incident. A maintainer handed the package to a stranger, who shipped wallet-stealing code that reached millions of installs through a transitive dependency.
Diagram
YOUR DEPENDENCY TREE β the risk is not at the top
your-app
βββ react you chose this
βββ some-ui-kit you chose this
β βββ lodash you didn't
β βββ color-parser you didn't
β β βββ tiny-helper β compromised β you've never heard of it
β βββ date-utils
βββ build-tool
βββ 340 more packages β postinstall scripts run as YOU
Direct deps: ~20. Actually installed: ~1,200.FOUR WAYS A PACKAGE TURNS HOSTILE
1. Maintainer account taken over (weak password, no 2FA)
2. Maintainer handover (event-stream)
3. Typosquatting reakt, lodahs, croos-env
4. Dependency confusion internal name published publicly,
registry prefers the public oneWHERE THE CODE ACTUALLY RUNS
npm install βββΊ postinstall script βββΊ your laptop, your CI,
your secrets, your tokens
build βββΊ bundled βββββββββββββββΊ every user's browser
A malicious package doesn't need to be imported to run.How it works
- Lockfile always committed. Without it, a fresh CI install can resolve a different, newer, compromised version.
- Audit in CI, not manually:
npm audit --audit-level=highas a gate, plus Dependabot or Renovate for patches. - Reduce the tree. Every dependency removed is a permanent risk reduction β do you need a package for
isArray? - Disable install scripts where possible (
npm ci --ignore-scripts) and pin exact versions for anything sensitive. - Prefix internal packages on a private scope so dependency confusion can't substitute a public one.
Trade-offs
| Practice | Cost |
|---|---|
| Pin exact versions | Manual patch upgrades |
--ignore-scripts | Some packages genuinely need them |
| Fewer dependencies | More code you maintain |
| Fast patching | Churn, regression risk |
Vet before adding: downloads and recency, open issue response time, number of maintainers, install-script presence, and whether the same job can be done in 20 lines of your own code.
Interview angle
"
npm auditreports 40 vulnerabilities. What do you do?"
- Triage by reachability first: a dev-only build tool's ReDoS is not a production incident.
- Fix anything reaching production or with network/filesystem access; patch the rest on a schedule.
- Then fix the process β audit gate in CI, automated patch PRs, and lockfile discipline.
Recap
- Transitive dependencies are the real surface, and install scripts run before any code review.
- Lockfile, CI audit gate, automated patches, fewer packages.
- Vet on maintainer health, not just on GitHub stars.