Dependency Audit
Read-only analysis patterns for dependency security, license compliance, and health assessment. This skill does NOT auto-upgrade packages -- it helps you understand your dependency landscape and make informed decisions.
Security-First Principles
| Principle | Practice | |-----------|----------| | Audit before merge | Run security checks in CI on every PR | | Understand before upgrading | Read changelogs, check breaking changes | | Never blindly force-fix | npm audit fix --force can introduce breaking changes | | Pin production dependencies | Use exact versions or lock files | | Verify publisher identity | Check package ownership, download counts, repo activity |
Security Audit Workflow
Step 1: Run the Audit
# npm (built-in)
npm audit
# npm -- JSON output for parsing
npm audit --json
# Yarn
yarn audit
# pnpm
pnpm audit
Step 2: Read the Report
# Example npm audit output
┌───────────────┬──────────────────────────────────────────────┐
│ Severity │ high │
├───────────────┼──────────────────────────────────────────────┤
│ Package │ lodash │
│ Dependency of │ my-library │
│ Path │ my-library > lodash │
│ More info │ https://github.com/advisories/GHSA-xxxx-xxxx │
└───────────────┴──────────────────────────────────────────────┘
Step 3: Assess Each Vulnerability
| Severity | CVSS Score | Action | |----------|-----------|--------| | Critical | 9.0-10.0 | Fix immediately, block deployment | | High | 7.0-8.9 | Fix within 24 hours | | Moderate | 4.0-6.9 | Fix within 1 week, assess exploitability | | Low | 0.1-3.9 | Track, fix in next maintenance window | | Info | 0 | Informational, no action required |
Step 4: Determine Fix Strategy
# SAFE: See what non-breaking fixes are available
npm audit fix --dry-run
# SAFE: Apply only semver-compatible fixes
npm audit fix
# DANGEROUS: Never run without understanding consequences
# npm audit fix --force <-- CAN INTRODUCE BREAKING CHANGES
# INVESTIGATE: When audit fix doesn't resolve
npm ls <vulnerable-package> # See dependency tree
npm explain <vulnerable-package> # See why it's installed
Step 5: Handle Unresolvable Vulnerabilities
When a vulnerability exists in a transitive dependency with no fix available:
# Check if the vulnerable code path is actually used
# Read the advisory -- is it relevant to your usage?
# Option A: Override the transitive dependency (npm)
# In package.json:
{
"overrides": {
"vulnerable-package": ">=fixed-version"
}
}
# Option B: Override the transitive dependency (yarn)
# In package.json:
{
"resolutions": {
"vulnerable-package": ">=fixed-version"
}
}
# Option C: Exclude from audit (document why)
# Create .nsprc or use npm audit --omit=dev for dev-only deps
Third-Party Scanning Tools
| Tool | Type | Best For | |------|------|----------| | npm audit | Built-in | Quick check, CI integration | | Snyk | SaaS + CLI | Deep analysis, fix PRs, monitoring | | Socket.dev | SaaS + CLI | Supply chain attack detection | | Dependabot | GitHub native | Automated update PRs | | Renovate | Self-hosted/SaaS | Highly configurable update PRs | | OSV-Scanner | CLI | Google's vulnerability database |
Snyk CLI Usage
# Install
npm install -g snyk
# Authenticate
snyk auth
# Test for vulnerabilities (read-only)
snyk test
# Monitor project (sends to dashboard)
snyk monitor
# Test a specific package before installing
snyk test <package-name>
OSV-Scanner Usage
# Install
go install github.com/google/osv-scanner/cmd/osv-scanner@latest
# Scan lock file
osv-scanner --lockfile=package-lock.json
# Scan entire directory
osv-scanner -r .
License Compatibility
Common License Types
| License | Type | Can Use In Commercial | Must Open Source Your Code | Must Include License | |---------|------|----------------------|--------------------------|---------------------| | MIT | Permissive | Yes | No | Yes | | Apache-2.0 | Permissive | Yes | No | Yes (+ NOTICE file) | | BSD-2-Clause | Permissive | Yes | No | Yes | | BSD-3-Clause | Permissive | Yes | No | Yes | | ISC | Permissive | Yes | No | Yes | | GPL-2.0 | Copyleft | Yes | Yes (if distributed) | Yes | | GPL-3.0 | Copyleft | Yes | Yes (if distributed) | Yes | | LGPL-2.1 | Weak Copyleft | Yes | Only modifications to LGPL code | Yes | | AGPL-3.0 | Strong Copyleft | Yes | Yes (even for network use) | Yes | | MPL-2.0 | Weak Copyleft | Yes | Only modified MPL files | Yes | | Unlicense | Public Domain | Yes | No | No | | SSPL | Source Available | Check terms | Yes (broad scope) | Yes | | BSL | Source Available | After change date | Before change date, restricted | Yes |
Compatibility Matrix (Can A Include B?)
| Your Project | MIT | Apache-2.0 | GPL-2.0 | GPL-3.0 | AGPL-3.0 | |-------------|-----|-----------|---------|---------|----------| | MIT | Yes | Yes | No | No | No | | Apache-2.0 | Yes | Yes | No | No | No | | GPL-2.0 | Yes | No | Yes | No | No | | GPL-3.0 | Yes | Yes | Yes | Yes | No | | AGPL-3.0 | Yes | Yes | Yes | Yes | Yes |
Checking Licenses
# List all dependency licenses
npx license-checker --summary
# Check for problematic licenses
npx license-checker --failOn "GPL-2.0;GPL-3.0;AGPL-3.0"
# Export full report
npx license-checker --csv --out licenses.csv
# Production only (skip devDependencies)
npx license-checker --production --summary
CI License Check
# GitHub Actions step
- name: Check licenses
run: |
npx license-checker --production \
--failOn "GPL-2.0;GPL-3.0;AGPL-3.0;SSPL-1.0" \
--excludePackages "known-exception@1.0.0"
Dependency Health Indicators
Red Flags
| Indicator | Risk | Check | |-----------|------|-------| | No updates in 2+ years | Unmaintained, unpatched vulns | npm view <pkg> time | | Single maintainer | Bus factor of 1 | Check GitHub contributors | | No tests or CI | Quality unknown | Check repo for test config | | Frequent ownership changes | Possible supply chain risk | Check npm ownership history | | Typosquat name | Malicious package | Verify exact package name | | Post-install scripts | Can execute arbitrary code | Check scripts.postinstall | | Excessive permissions | Over-scoped access | Review package contents | | Many open security issues | Known vulnerabilities | Check GitHub issues/advisories |
Health Check Commands
# View package metadata
npm view <package-name>
# Check when last published
npm view <package-name> time --json | jq 'to_entries | sort_by(.value) | last'
# See who maintains it
npm view <package-name> maintainers
# Check download counts (popularity signal)
npm view <package-name> --json | jq '.dist-tags, .versions | length'
# List all postinstall scripts in dependencies
npm ls --json | jq '.. | .scripts?.postinstall? // empty'
# Check package size before installing
npx package-phobia <package-name>
Before Adding a New Dependency
Ask these questions before npm install:
- [ ] Is this package actively maintained? (Commits in last 6 months)
- [ ] Does it have more than one maintainer?
- [ ] Are there open, unresolved security issues?
- [ ] Is the license compatible with my project?
- [ ] What is the install size and bundle size impact?
- [ ] Does it have post-install scripts? Are they necessary?
- [ ] Could I implement this functionality in <50 lines?
- [ ] Is this a direct dependency or could it be a devDependency?
Safe Upgrade Strategy
The Read-Analyze-Test-Upgrade Cycle
Never upgrade blindly. Follow this cycle for each upgrade.
Step 1: Identify Available Updates
# See what's outdated (read-only)
npm outdated
# More detail
npm outdated --long
# Output:
# Package Current Wanted Latest Location
# express 4.18.2 4.18.3 5.0.0 my-app
# lodash