| name | install-dependencies-rules |
| description | Use this skill ALWAYS before adding, updating, or removing any dependency in a Node.js project. Applies to frontend, backend, and monorepos. Covers mandatory pnpm usage, exact pinning without carets, querying the latest stable version, post-install auditing, protection against compromised packages with free tools, and Dependabot for controlled updates.
|
Dependency Installation Rules
Agent workflow — every time a dependency is installed
- Evaluate whether the dependency is necessary (section Before Installing).
- Query the latest stable version with
pnpm view before running pnpm add.
- Install with pnpm, no carets, with an explicit exact version.
- Audit immediately after installation (
pnpm audit + osv-scanner).
- Verify that CI runs
pnpm audit --audit-level=high and osv-scanner.
- Confirm Dependabot is configured to receive controlled update PRs.
Cross-references
| Skill | When to activate |
|---|
basic-workflows | Configuring the pnpm audit step in CI and Dependabot in the repository |
security | If the dependency exposes endpoints or handles data — review security implications |
Before Installing — Mandatory Checklist
Before running any pnpm add, answer these questions:
| Question | Acceptance criterion |
|---|
| Is it really necessary? | Cannot be implemented with native API (Node.js / browser) in < 30 lines |
| Is it maintained? | Last release < 6 months ago; issues responded to; active repository |
| Does it have adoption? | > 10K weekly downloads on npm |
| Is the version correct? | Checked with pnpm view <package> (see next section) |
| Does it have types? | Includes .d.ts or @types/<package> exists |
| Is it tree-shakeable? | Exports ESM with named imports — doesn't import the entire bundle |
| How much does it weigh? | Check on bundlephobia.com — prefer an alternative if size is excessive |
| Is the license compatible? | MIT, Apache 2.0, ISC, BSD → OK. GPL → requires approval |
| Is it free from malware? | Scanned with osv-scanner or socket before merging |
Query metadata before installing
pnpm view <package>
pnpm view <package> version
pnpm view <package> versions --json
pnpm view <package> dist-tags
pnpm view <package> repository license dependencies
Always install the latest version unless there is a documented reason for an older one.
Secure Installation
Golden rules
- pnpm only — never
npm install or yarn add in the project.
- Pin exact, no carets or tildes —
"zod": "3.23.8" not "zod": "^3.23.8".
- Explicit version —
pnpm add zod@3.23.8, not pnpm add zod (even though it installs latest, the lockfile gets ^).
- Separate
dependencies and devDependencies — use -D for everything that doesn't reach production.
pnpm add zod@3.23.8
pnpm add -D vitest@2.1.9
pnpm add zod
pnpm add -D vitest
Why no carets?
A caret (^) allows pnpm install on another machine or in CI to resolve a higher minor version without the team consciously deciding to upgrade. The most common supply chain attacks (e.g., event-stream, ua-parser-js, colors) spread exactly this way: via a compromised minor or patch version that silently enters projects using carets.
Instead: exact pin + Dependabot creates PRs for each update → the team reviews before merging.
Configure .npmrc to enforce the rule
auto-install-peers=true
strict-peer-dependencies=false
shamefully-hoist=false
resolution-mode=highest
prefer-frozen-lockfile=true
save-exact=true
With save-exact=true, pnpm add zod will save "zod": "3.23.8" instead of "zod": "^3.23.8" automatically.
package.json — declare environment versions
{
"packageManager": "pnpm@9.15.0",
"engines": {
"node": ">=20.0.0",
"pnpm": ">=9.0.0"
}
}
.nvmrc — pin Node version
20.18.0
Day-to-Day Operations
Maintenance commands — do not require the new installation checklist:
pnpm add -D -w eslint
pnpm update
pnpm update --latest
pnpm update react --latest
pnpm remove lodash
pnpm outdated
pnpm store prune
pnpm dedupe
Post-Install Audit
Run both tools after each installation or update:
1. pnpm audit (npm advisory database)
pnpm audit
pnpm audit --audit-level=high
pnpm audit --fix
2. OSV-Scanner (Google's OSV database — free)
Scans pnpm-lock.yaml against the Open Source Vulnerabilities database, which is broader than npm's:
brew install osv-scanner
osv-scanner --lockfile=pnpm-lock.yaml
osv-scanner --recursive .
Free Protection Tools
| Tool | What it detects | How to use | Free |
|---|
pnpm audit | Known CVEs in npm advisory | pnpm audit | ✅ Always |
| OSV-Scanner (Google) | CVEs in OSV DB (broader than npm) | CLI + GitHub Action | ✅ Always |
| Dependabot (GitHub) | Outdated dependencies with CVEs | .github/dependabot.yml | ✅ Public and private repos |
| Socket.dev | Packages with suspicious behavior (typosquatting, supply chain) | GitHub App + npx socket | ✅ Free app for public repos |
| Snyk | CVEs + license compliance | npx snyk test | ✅ Individual tier |
Socket.dev — compromised package detection
Socket analyzes the actual code behavior of a package (network access, file system access, obfuscation) — goes beyond known CVEs.
npx @socketsecurity/cli npm info <package>@<version>
GitHub App (free for public repos): install from socket.dev to automatically review every PR that modifies package.json.
OSV-Scanner in GitHub Actions
- name: Run OSV-Scanner
uses: google/osv-scanner-action@v1
with:
scan-args: |-
--lockfile=./pnpm-lock.yaml
Dependabot — Controlled Updates
With everything pinned exactly, Dependabot is the only update gate: it creates individual PRs per dependency that the team reviews and merges.
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: "09:00"
open-pull-requests-limit: 5
groups:
dev-deps:
patterns: ["*"]
dependency-type: development
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
With groups, Dependabot bundles all devDeps into a single weekly PR instead of dozens of individual ones.
CI — Mandatory Security Steps
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Audit (npm advisory)
run: pnpm audit --audit-level=high
- name: OSV-Scanner
uses: google/osv-scanner-action@v1
with:
scan-args: |-
--lockfile=./pnpm-lock.yaml
Overrides and Patches
When a transitive dependency has a vulnerability and the author hasn't released a fix:
{
"pnpm": {
"overrides": {
"glob@<9": ">=9.0.0",
"semver@<7.5.2": ">=7.5.2"
},
"patchedDependencies": {
"buggy-lib@1.2.3": "patches/buggy-lib@1.2.3.patch"
}
}
}
pnpm patch buggy-lib@1.2.3
pnpm patch-commit <temp-folder>
After applying overrides, verify with pnpm audit and osv-scanner — if the audit passes, the risk is mitigated.
package.json Scripts
Canonical script set for any team project:
{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"type-check": "tsc --noEmit",
"test": "vitest",
"test:ci": "vitest run --coverage",
"test:e2e": "playwright test",
"analyze": "ANALYZE=true next build",
"clean": "rm -rf .next node_modules/.cache",
"prepare": "husky"
}
}
Mandatory Rules
- pnpm only —
npm install, yarn add, npx install-* are prohibited in any team project.
save-exact=true in .npmrc — configured from the repository's initial commit.
- Always pin exact — no carets, no tildes, in
dependencies and devDependencies.
pnpm view <package> before pnpm add — never install without verifying the latest stable.
pnpm audit immediately after installation — do not open a PR with high/critical vulnerabilities.
osv-scanner --lockfile in CI — non-optional step; fails the pipeline if vulnerabilities are found.
- Dependabot configured — from the repository's initial commit.
--frozen-lockfile in CI — without exception; if it fails, the developer updates the lockfile locally.
packageManager and engines declared in package.json.
- Do not install packages with < 1K weekly downloads without manually reviewing the source code.
Gotchas
pnpm add <package> without a version with save-exact=false saves a caret — verify .npmrc has save-exact=true before the first pnpm add.
pnpm audit --fix can introduce automatic overrides that break features — review the package.json diff after running it.
- Dependabot doesn't group by default — without
groups, it generates one PR per dependency and floods notification inboxes.
osv-scanner on macOS requires Go or Homebrew — document installation in the project's CONTRIBUTING.md.
- Updating Node without updating
.nvmrc creates inconsistencies between dev and CI — both must be updated together.
- Socket.dev GitHub App is only free for public repos — for private repos, evaluate a paid tier or run
npx @socketsecurity/cli manually during periodic security reviews.
- Runtime dependencies in
devDependencies (or vice versa) break production builds or inflate the bundle — always verify whether a dependency is used at runtime.
- Floating versions (
"*" or "latest") in sub-dependencies can still arrive via transitive deps — use pnpm.overrides to pin them; the app's lockfile alone is not enough.