Dependency Management and Security Scanning
Dependency Management and Security Scanning
The average JavaScript project has 200+ transitive dependencies. The average Python project has 50+. Every one of them is attack surface. Supply chain attacks — compromising a widely-used package to inject malicious code — went from theoretical to routine. Dependency management is now a security concern, not just a convenience feature.
Lockfile Hygiene
Lockfiles pin your dependencies to exact versions. Without them, npm install on your machine and npm install in CI might install different versions.
What lockfiles do
# npm: package-lock.json
npm install # Reads package-lock.json, installs exact versions
npm install --no-save # Installs from lockfile without modifying it
# Bun: bun.lock
bun install # Reads bun.lock
# pnpm: pnpm-lock.yaml
pnpm install --frozen-lockfile # Fails if lockfile is out of date (use in CI)
# Python (pip): requirements.txt with hashes
pip install -r requirements.txt --require-hashes
# Go: go.sum
go mod verify # Verifies checksums match go.sum
Rules:
- Always commit your lockfile
- In CI, use
--frozen-lockfile(pnpm),npm ci(npm), or equivalent — fail the build if the lockfile is out of date - Review lockfile changes in PRs — a lockfile diff that changes 500 packages when you added one dependency deserves scrutiny
Bun's lockfile
Bun uses a binary lockfile (bun.lock) which is faster to read/write but harder to review in diffs. For teams that need readable lockfile diffs:
# Generate human-readable text lockfile
bun install --save-text-lockfile
Vulnerability Scanning
npm audit / bun audit
Built-in vulnerability checking:
# Check for known vulnerabilities
npm audit
# Fix automatically where possible
npm audit fix
# Only show high/critical severity
npm audit --audit-level=high
npm audit checks the GitHub Advisory Database. It's a good starting point but has false positives and sometimes flags vulnerabilities in dev dependencies that aren't exploitable in production.
Trivy
Trivy is an open-source vulnerability scanner that handles dependencies, container images, IaC files, and more.
brew install trivy
# Scan a project directory (detects package.json, go.mod, requirements.txt, etc.)
trivy fs .
# Scan only for high/critical vulnerabilities
trivy fs --severity HIGH,CRITICAL .
# Scan a Docker image
trivy image my-app:latest
# Scan with SBOM output (Software Bill of Materials)
trivy fs --format spdx-json -o sbom.json .
# In CI: fail the build if critical vulnerabilities found
trivy fs --exit-code 1 --severity CRITICAL .
Trivy supports: npm, yarn, pnpm, pip, poetry, Go modules, Cargo (Rust), Maven, Gradle, NuGet, and more. It's the best free option for multi-language projects.
Snyk
Snyk is a commercial vulnerability scanning platform with a generous free tier.
npm install -g snyk
# Authenticate
snyk auth
# Test for vulnerabilities
snyk test
# Monitor continuously (reports new vulnerabilities as they're disclosed)
snyk monitor
# Fix vulnerabilities (opens PRs with updates)
snyk fix
Snyk's key advantage over npm audit is fix PRs: it can automatically open pull requests that update vulnerable dependencies to safe versions, including testing if the update breaks anything.
Pricing: Free for open source. 200 tests/month on private repos. Paid plans from $25/developer/month.
Socket
Socket takes a different approach: instead of checking a vulnerability database, it analyzes package behavior. It detects:
- Packages that access the network unexpectedly
- Packages that execute shell commands
- Packages with install scripts that run arbitrary code
- Packages that access environment variables or filesystem
npm install -g socket
socket npm info lodash
Socket catches supply chain attacks that vulnerability databases miss because the attack is new (zero-day). It's complementary to Snyk/Trivy, not a replacement.
Automated Dependency Updates
Renovate
Renovate is an open-source tool that automatically opens PRs to update dependencies. It's more configurable than Dependabot.
// renovate.json
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"packageRules": [
{
"matchUpdateTypes": ["patch"],
"automerge": true
},
{
"matchUpdateTypes": ["major"],
"labels": ["breaking-change"],
"reviewers": ["team:platform"]
},
{
"matchPackageNames": ["typescript", "eslint"],
"groupName": "tooling"
}
],
"schedule": ["before 7am on Monday"]
}
Key features:
- Auto-merge patch updates (with passing CI)
- Group related updates into single PRs
- Respect semver ranges
- Schedule updates to avoid disruption
- Support for monorepos
Dependabot
GitHub's built-in dependency updater. Simpler than Renovate but less configurable.
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
reviewers:
- "your-team"
Renovate vs Dependabot: Renovate is more configurable (grouping, scheduling, auto-merge rules, monorepo support). Dependabot is simpler to set up and built into GitHub. For small projects, Dependabot is fine. For monorepos or teams with specific update policies, Renovate is worth the setup.
License Compliance
Some open-source licenses have requirements that affect commercial software. GPL requires derivative works to also be open-source. AGPL extends this to network use (SaaS). Most permissive licenses (MIT, Apache 2.0, BSD) have no such requirements.
license-checker
npx license-checker --summary
npx license-checker --failOn "GPL-2.0;GPL-3.0;AGPL-3.0"
npx license-checker --production # Only check production dependencies
Trivy License Scanning
trivy fs --scanners license --severity HIGH .
Add license checks to CI if your company has compliance requirements. Most startups can skip this initially, but enterprise customers often require it.
CI Pipeline Example
A practical dependency security pipeline in GitHub Actions:
# .github/workflows/security.yml
name: Dependency Security
on:
pull_request:
schedule:
- cron: '0 8 * * 1' # Weekly Monday 8am
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
severity: 'HIGH,CRITICAL'
exit-code: '1'
- name: License check
run: npx license-checker --failOn "GPL-3.0;AGPL-3.0" --production
Recommendations
- Start with what's free: npm audit + Trivy covers most needs
- Automate updates: Renovate (or Dependabot) keeps dependencies from drifting months behind
- Scan in CI: Block merges when critical vulnerabilities are found
- Auto-merge patches: If CI passes and it's a patch update, merge it automatically
- Review major updates manually: Breaking changes need human review
- Don't ignore dev dependencies: A compromised build tool can inject code into your production bundle