Protect against supply chain attacks and malicious dependencies. Learn dependency auditing, lockfiles, private registries, SBOM generation, and CI security scanning.
Dependency Security and Supply Chain
NPM Security Audit
# Check for vulnerabilities
npm audit
npm audit --audit-level=high # Fail only on high/critical
# Auto-fix where possible
npm audit fix
# Detailed JSON report
npm audit --json > audit-report.json
# Check for outdated packages
npm outdated
# Use socket.dev for deep analysis
npx socket npm install lodash
Lockfile Best Practices
# Always commit lockfiles
git add package-lock.json # or yarn.lock / pnpm-lock.yaml
# Use --frozen-lockfile in CI
npm ci # Respects package-lock.json exactly
yarn install --frozen-lockfile
pnpm install --frozen-lockfile
# Verify lockfile integrity
npm ci --audit
Dependency Pinning
{
"dependencies": {
"express": "4.18.2", // Pinned - GOOD
"lodash": "^4.17.21", // ^ allows minor/patch - acceptable
"react": "~18.2.0", // ~ allows only patch - acceptable
"some-pkg": "*" // Wildcard - DANGEROUS
}
}
GitHub Actions Security Scanning
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
dependency-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: NPM Audit
run: npm audit --audit-level=high
- name: Snyk vulnerability scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'myapp'
path: '.'
format: 'HTML'
args: --failOnCVSS 7
secret-scanning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for secret scanning
- name: Gitleaks scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
languages: javascript, typescript
SBOM (Software Bill of Materials)
# Generate SBOM with CycloneDX
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --output-file sbom.json
# Generate SBOM with Syft
syft packages . --output spdx-json=sbom.spdx.json
# Scan SBOM against vulnerability databases
grype sbom:./sbom.json
# Store SBOM in CI artifacts
Private Package Registry
# Use Verdaccio for private npm registry
npm install -g verdaccio
verdaccio
# Configure npm to use private registry
npm set registry http://localhost:4873/
# .npmrc for project
@mycompany:registry=https://npm.company.com
//npm.company.com/:_authToken=${NPM_TOKEN}
# Block public packages with same name (namespace squatting prevention)
# package.json
{
"name": "@mycompany/internal-lib", // Scoped package
"private": true
}
Pre-commit Secret Detection
# Install pre-commit
pip install pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
- repo: https://github.com/zricethezav/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
# Initialize
pre-commit install
pre-commit run --all-files
Typosquatting Detection
import requests
from difflib import SequenceMatcher
def check_typosquatting(package_name: str, threshold: float = 0.85) -> list:
"""Check if a package name is suspiciously similar to popular packages."""
popular_packages = [
"express", "react", "lodash", "axios", "moment",
"webpack", "babel", "eslint", "prettier", "typescript"
]
suspicious = []
for popular in popular_packages:
similarity = SequenceMatcher(None, package_name, popular).ratio()
if similarity > threshold and package_name != popular:
suspicious.append({
"package": package_name,
"similar_to": popular,
"similarity": similarity,
})
return suspicious
# Check before installing
result = check_typosquatting("expres") # Missing 's'
if result:
print(f"WARNING: Possible typosquatting: {result}")
Security Policies
# .github/SECURITY.md template highlights:
# - Supported versions table
# - Vulnerability reporting process
# - Response timeline (24h acknowledge, 7d fix)
# Dependabot auto-updates
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
labels:
- "security"
open-pull-requests-limit: 10