TechLead
Lesson 8 of 9
5 min read
Web Security

Dependency Security

Keep your dependencies secure with vulnerability scanning, lock files, and automated updates.

Managing Dependency Security

Third-party dependencies are a major attack vector. Supply chain attacks, vulnerable packages, and malicious code can compromise your entire application.

Vulnerability Scanning

npm audit

# Check for vulnerabilities
npm audit

# Get JSON output for CI/CD
npm audit --json

# Fix automatically where possible
npm audit fix

# Force fix (may include breaking changes)
npm audit fix --force

# Only check production dependencies
npm audit --production

Snyk

# Install Snyk
npm install -g snyk

# Authenticate
snyk auth

# Test for vulnerabilities
snyk test

# Monitor project continuously
snyk monitor

# Fix vulnerabilities
snyk fix

Lock Files

# Always commit lock files
# package-lock.json (npm)
# yarn.lock (Yarn)
# pnpm-lock.yaml (pnpm)

# Use exact versions in CI
npm ci  # Instead of npm install

# Verify integrity
npm ci --ignore-scripts

Automated Updates with Dependabot

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

    # Group minor and patch updates
    groups:
      minor-and-patch:
        update-types:
          - "minor"
          - "patch"

    # Ignore specific packages
    ignore:
      - dependency-name: "aws-sdk"
        update-types: ["version-update:semver-major"]

    # Security updates only
    # schedule:
    #   interval: "daily"
    # open-pull-requests-limit: 20

Renovate Bot Configuration

// renovate.json
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:base",
    ":semanticCommits",
    "schedule:weekly"
  ],
  "packageRules": [
    {
      "matchUpdateTypes": ["minor", "patch"],
      "groupName": "minor and patch updates",
      "automerge": true
    },
    {
      "matchPackagePatterns": ["eslint", "prettier"],
      "groupName": "linting tools"
    },
    {
      "matchDepTypes": ["devDependencies"],
      "automerge": true
    }
  ],
  "vulnerabilityAlerts": {
    "enabled": true,
    "labels": ["security"]
  }
}

Pre-install Script Checking

// package.json
{
  "scripts": {
    "preinstall": "npx npm-run-all check:*",
    "check:audit": "npm audit --audit-level=high",
    "check:licenses": "license-checker --production --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC'"
  }
}

Using npm-shrinkwrap for Production

# Create shrinkwrap file (more strict than package-lock.json)
npm shrinkwrap

# This creates npm-shrinkwrap.json which:
# - Takes precedence over package-lock.json
# - Is published with the package
# - Ensures exact dependency tree in production

Subresource Integrity (SRI) for CDN

<!-- Always use SRI when loading from CDN -->
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

<link
  rel="stylesheet"
  href="https://cdn.example.com/styles.css"
  integrity="sha384-..."
  crossorigin="anonymous"
>
# Generate SRI hash
echo -n "console.log('hello');" | openssl dgst -sha384 -binary | openssl base64 -A

# Or use srihash.org

Private Registry

# .npmrc for private registry
registry=https://registry.npmjs.org/
@mycompany:registry=https://npm.mycompany.com/

# Verdaccio for self-hosted registry
npm install -g verdaccio
verdaccio

# Publish to private registry
npm publish --registry https://npm.mycompany.com/

GitHub Actions Security Workflow

# .github/workflows/security.yml
name: Security Check

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * *'  # Daily

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run npm audit
        run: npm audit --audit-level=high

      - name: Run Snyk
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

      - name: Check licenses
        run: |
          npx license-checker --production --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC'

Best Practices

  • Always commit lock files
  • Use npm ci in CI/CD
  • Run npm audit regularly
  • Set up automated dependency updates
  • Use SRI for CDN resources
  • Review dependency changes in PRs
  • Minimize dependencies (prefer standard library)
  • Check package health before installing
  • Use scoped packages for internal code
  • Consider using a private registry

Continue Learning