Skip to main content

04 - SCA - Software Composition Analysis and Dependency Vulnerabilities

SCA tools (Snyk, Black Duck, Dependabot), vulnerability database (NVD, CVE), transitive dependency analysis, license management, update strategies, compliance tracking.

What do you think about this article?

At a Glance

SCA tools (Snyk, Black Duck, Dependabot), vulnerability database (NVD, CVE), transitive dependency analysis, license management, update strategies, compliance tracking.

SCA: What is Software Composition Analysis

SCA (Software Composition Analysis) is the practice of analyzing a project's open source dependencies to identify known vulnerabilities, licensing issues, and risks in the software supply chain. With over 90% of modern code using open source components, dependency security has become a critical aspect.

Unlike SAST which analyzes team-written code, SCA focuses on imported code: npm libraries, pip packages, Maven dependencies, Ruby gems, and any other third-party components. A single vulnerability in a widely-used library can expose thousands of applications, as demonstrated by the Log4Shell and XZ Utils incidents.

In this article, we will explore the main SCA tools, transitive dependency management, license tracking, and strategies for keeping dependencies up to date.

What You'll Learn

  • How SCA works and transitive dependency analysis
  • Configuring Snyk, Dependabot, and OWASP Dependency-Check
  • Vulnerability databases: NVD, CVE, GitHub Advisory
  • Open source license management and compliance
  • Update strategies: automatic vs manual patches
  • SCA integration in the CI/CD pipeline

The Transitive Dependency Problem

A typical project has dozens of direct dependencies, but each of these brings its own dependencies (transitive). A Node.js project with 50 direct dependencies can have 500-1000 transitive dependencies in node_modules.

Vulnerabilities in transitive dependencies are particularly insidious because developers might not be aware of their existence. SCA analyzes the entire dependency tree, including transitive ones, to ensure complete coverage.

Why SCA is Critical

The Log4Shell incident (CVE-2021-44228) demonstrated the devastating impact of a vulnerability in a widely-used library: over 35,000 Java packages were vulnerable. Many organizations took weeks to identify all affected applications because they didn't have a dependency inventory. SCA prevents this scenario by maintaining an updated inventory and alerting immediately when a new vulnerability is discovered.

Snyk: Developer-Integrated SCA

Snyk is a modern SCA platform that integrates directly into the developer workflow. It offers a free plan for open source projects and an excellent developer experience with IDE, CLI, and CI/CD integration.

Snyk CLI: Terminal Analysis


# Install Snyk CLI
npm install -g snyk

# Authenticate
snyk auth

# Analyze project dependencies
snyk test

# Analyze and monitor (registers in dashboard)
snyk monitor

# Analyze a Dockerfile
snyk container test node:18-alpine

# Analyze IaC code
snyk iac test terraform/

# JSON output for automation
snyk test --json --severity-threshold=high > snyk-results.json
      

Snyk Integration in GitHub Actions


# .github/workflows/snyk.yml
name: Snyk Security Scan
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

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

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

      - name: Install dependencies
        run: npm ci

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

      - name: Snyk Monitor
        if: github.ref == 'refs/heads/main'
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          command: monitor
      

Dependabot: GitHub's Automatic Updates

Dependabot is GitHub's integrated service that monitors dependencies and automatically creates pull requests to update vulnerable versions. Configuration is simple and done through a YAML file in the repository.


# .github/dependabot.yml
version: 2
updates:
  # npm dependencies
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
      time: "09:00"
      timezone: "Europe/Rome"
    open-pull-requests-limit: 10
    reviewers:
      - "security-team"
    labels:
      - "dependencies"
      - "security"
    ignore:
      - dependency-name: "*"
        update-types: ["version-update:semver-major"]
    groups:
      dev-dependencies:
        dependency-type: "development"
        update-types:
          - "minor"
          - "patch"

  # GitHub Actions
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

  # Docker
  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"
      

OWASP Dependency-Check

OWASP Dependency-Check is an open source SCA tool that identifies project dependencies and checks if they have known vulnerabilities in the National Vulnerability Database (NVD). It supports Java, .NET, Node.js, Python, Ruby, and many other ecosystems.


# .github/workflows/dependency-check.yml
name: OWASP Dependency Check
on:
  push:
    branches: [main]
  schedule:
    - cron: "0 6 * * 1"  # Every Monday at 6:00 AM

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

      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main
        with:
          project: "my-application"
          path: "."
          format: "HTML"
          args: >
            --failOnCVSS 7
            --enableRetired
            --nvdApiKey ${{ secrets.NVD_API_KEY }}

      - name: Upload Report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: dependency-check-report
          path: reports/
      

Vulnerability Databases

SCA tools rely on known vulnerability databases to identify problematic dependencies. The main databases are:

Main Vulnerability Databases

Database Maintainer Coverage
NVD (National Vulnerability Database) NIST (US Gov) All platforms, 24-48h updates
GitHub Advisory Database GitHub npm, pip, Maven, RubyGems, NuGet, Go
OSV (Open Source Vulnerability) Google Multi-ecosystem, open format
Snyk Vulnerability DB Snyk Manually curated, high quality

Open Source License Management

Beyond vulnerabilities, SCA analyzes dependency licenses to ensure legal compliance. Some open source licenses (like GPL and AGPL) have copyleft requirements that can have significant implications for commercial software.

  • Permissive (MIT, Apache 2.0, BSD): free use, few restrictions
  • Weak Copyleft (LGPL, MPL): modifications to the library must be released under the same license
  • Strong Copyleft (GPL, AGPL): all derived software must be released under the same license
  • Proprietary/Non-standard: require case-by-case legal review

Recommended License Policy

  • Approved: MIT, Apache 2.0, BSD 2/3-Clause, ISC
  • Review required: LGPL, MPL, CC-BY
  • Blocked: GPL, AGPL, SSPL (for proprietary software)
  • Unknown: require legal review before use

Dependency Update Strategies

Keeping dependencies updated is an ongoing challenge. Here are the strategies we recommend:

1. Automatic Patches for Critical Vulnerabilities

Configure Dependabot or Renovate to automatically create PRs for security updates. Security patches (minor/patch versions) can be auto-merged if tests pass, reducing exposure time.

2. Grouped Weekly Updates

Group non-critical updates into a single weekly PR to reduce noise and facilitate review. Dependabot supports groups natively.

3. Major Versions with Planning

Major version updates (breaking changes) must be planned and manually tested. Ignore automatic major updates and dedicate specific sprint time.

4. Lock Files and Reproducibility

Always use lock files (package-lock.json, yarn.lock, Pipfile.lock) to ensure reproducible builds and use npm ci instead of npm install in CI.

SCA in the Pipeline: Complete Workflow


# .github/workflows/sca-complete.yml
name: SCA Complete Workflow
on:
  push:
    branches: [main]
  pull_request:

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

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

      - name: Install dependencies
        run: npm ci

      - 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

  license-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: License check
        run: npx license-checker --failOn "GPL-2.0;GPL-3.0;AGPL-3.0"
      

SCA Best Practices

  1. Scan on every build: every pipeline should include an SCA check, not just nightly builds
  2. Continuous monitoring: register projects in Snyk/Dependabot to receive alerts when new CVEs are discovered
  3. License policies: define and automate acceptable license policies
  4. Minimal dependencies: critically evaluate every new dependency. Fewer dependencies means less attack surface
  5. Version pinning: use exact versions in lock files, not ranges
  6. Regular audits: quarterly dependency review to remove unused ones

Conclusions

SCA is a fundamental pillar of DevSecOps, particularly critical in the era of open source software. The combination of vulnerability scanning, license compliance, and automated updates protects the project from threats in the software supply chain.

In the next article, we'll explore Container Security, analyzing how to protect Docker images, implement image scanning with Trivy and Grype, and configure runtime protection for production containers.

Frequently asked questions

What is the main purpose of Software Composition Analysis (SCA)?

The main purpose of SCA is to analyze a project's open source dependencies to identify known vulnerabilities, licensing issues, and risks in the software supply chain.

How do transitive dependencies pose a risk to software security?

Transitive dependencies can be particularly insidious because developers might not be aware of their existence, making it difficult to identify vulnerabilities that could affect the entire project.

What is the benefit of using SCA tools like OWASP Dependency-Check and Dependabot?

These tools help maintain an updated inventory of dependencies and alert immediately when a new vulnerability is discovered, preventing scenarios like the Log4Shell incident where thousands of applications were vulnerable.

Why is it essential to use lock files in CI/CD pipelines for reproducible builds?

Lock files ensure that the same versions of dependencies are used across different environments, reducing the risk of introducing vulnerabilities or compatibility issues.

Sources and further reading

Try These Tools

Free developer tools related to this topic.

Commenti

Caricamento commenti...

Sign in to comment

Discuss this article in the community

Join the Telegram group to discuss with other developers, ask questions and share your experiences.

Did you like this article?

Explore other content on the blog or discover my projects