Insights Business| SaaS| Technology Implementing Software Composition Analysis: Trivy Integration and Reachability Analysis
Business
|
SaaS
|
Technology
Jan 2, 2026

Implementing Software Composition Analysis: Trivy Integration and Reachability Analysis

AUTHOR

James A. Wondrasek James A. Wondrasek
Graphic representation of the topic Software Supply Chain Security

Modern applications are built from third-party code. On average, 70-90% of what you ship comes from external libraries and dependencies. Every npm install, pip install, or go get pulls in code you didn’t write, creating an extensive attack surface.

Traditional vulnerability scanners flag every CVE they find in your dependencies. You end up with thousands of alerts where maybe 10-20% are actually exploitable in your application. The rest? Noise.

Reachability analysis changes this. It uses call graph analysis to identify which vulnerable code paths are actually invoked by your application. The result is an 80% reduction in false positives.

This guide is part of our comprehensive software supply chain security resource, focusing specifically on implementing Software Composition Analysis (SCA) with Trivy in GitHub Actions. You’ll get PR-blocking workflows, severity-based thresholds, and automated remediation. We’ll also cover the build-vs-buy decision framework so you know when free Trivy is sufficient and when enterprise features like Snyk’s reachability justify the cost.

The goal is a production-ready SCA pipeline that blocks vulnerabilities at PR time without burying your developers in alert fatigue.

What is Software Composition Analysis and Why Does It Matter?

SCA is the security practice of identifying, cataloguing, and monitoring risks in third-party dependencies and open-source components. It’s one piece of a multi-layered security strategy that secures external code while SAST handles your proprietary code.

The primary functions are vulnerability detection through CVE matching, licence compliance checking, transitive dependency tracking, and SBOM generation.

Transitive dependencies create hidden vulnerabilities. If package A depends on B, which depends on C, then C is a transitive dependency. You don’t directly control its version. Most developers don’t even know it exists. A vulnerable transitive dependency can expose your application.

Log4Shell demonstrated this. A remote-code-execution flaw in a widely used logging library made significant portions of the internet exploitable. Thousands of applications were affected through indirect dependencies they didn’t know they had.

If you’re running dozens of microservices, each service likely has hundreds of dependencies. Manual tracking doesn’t scale.

Regulatory compliance adds another layer. SOC 2 and ISO requirements often mandate SBOM artifacts. You need to know what’s in your software and prove you’re managing the risks.

SCA platforms also provide continuous monitoring. They check dependencies against CVE databases and notify teams when new vulnerabilities are detected in components already in production.

How Does Reachability Analysis Reduce False Positives in Vulnerability Scanning?

Traditional SCA reports every CVE present in dependencies. This is presence-based scanning. It causes alert fatigue because you get 1000+ findings where most are unexploitable.

Reachability analysis determines whether a discovered vulnerability can actually be exploited in your specific application context. It maps function calls from your application entry points through the full dependency tree, then identifies which vulnerable functions are never reached.

The technical mechanism is static analysis that generates a call graph from main() to all dependencies. It overlays CVE locations on the graph and flags only the vulnerabilities in code paths your application actually executes.

Consider a library with a function that has a remote code execution vulnerability. If your application never calls that function, the risk is theoretical. Without reachability checks, the issue would still be reported, creating noise for developers who then have to manually triage it.

Your team triages 50 alerts instead of 500. Development velocity improves when people spend less time on noise and more time on real threats.

The limitation is that reachability analysis requires sophisticated static analysis capabilities that vary by language. Snyk supports reachability for Java, JavaScript/TypeScript, and Python. Other languages may have limited or no support. Trivy does not natively support reachability analysis—it performs presence-based scanning only.

So why start with Trivy if it doesn’t do reachability? Because it’s free, fast, and gets you 90% of the way there. You can layer on reachability later when the cost of manual triage justifies paying for enterprise tools. While SCA focuses on detecting vulnerabilities in dependencies, developer environment security addresses prevention by hardening the tools and environments where developers work with those dependencies.

How to Integrate Trivy into GitHub Actions Workflow?

Trivy is an open-source vulnerability scanner from Aqua Security. It started as a container image scanning tool and evolved into a versatile scanner for file systems, code repositories, Dockerfiles, Kubernetes manifests, and more.

Installation is available as a GitHub Action (aquasecurity/trivy-action), CLI binary, or Docker image. The GitHub Action is the fastest integration path.

The basic workflow is: checkout code, install dependencies, run Trivy scan, fail pipeline if vulnerabilities exceed your threshold.

Here’s what that looks like. Add this to .github/workflows/security-scan.yml:

name: Security Scan
on:
  pull_request:
    branches: [main]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Upload Trivy results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v2
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Notify on Slack if scan fails
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "Security scan failed on PR #${{ github.event.pull_request.number }}"
            }

Configure the scan target (fs for file system, image for containers), severity filter (CRITICAL, HIGH), output format (table, json, sarif), and exit code behaviour.

This workflow triggers the scan on pull requests, runs Trivy against the repository root, blocks merge if CVSS >= 7.0, and uploads SARIF to GitHub Security tab for visibility.

Performance matters. Trivy is known for speed and efficiency—it can scan medium-sized container images in seconds. Cache the Trivy database and use incremental scanning by only checking changed lock files.

Here’s how to add caching:

- name: Cache Trivy DB
  uses: actions/cache@v3
  with:
    path: ~/.cache/trivy
    key: trivy-db-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      trivy-db-

Output destinations depend on your audience. Console table for developers reviewing PRs. SARIF for GitHub Security integration. JSON for OWASP Dependency-Track ingestion.

Trivy pulls data from various security databases, including NVD, GitHub Advisories, Sonatype OSS Index, and OSV. This broad coverage means you catch vulnerabilities from multiple intelligence sources.

Typical scan time is 30-90 seconds for a standard application with 50-200 dependencies. That’s fast enough to run on every pull request without slowing down your pipeline.

How to Configure PR Blocking Based on Vulnerability Severity?

PR blocking prevents merging code with policy violations. When vulnerabilities exceed your severity thresholds, the GitHub Actions workflow fails and the PR cannot merge.

Severity-based thresholds define acceptable risk levels. A common starting point is blocking CRITICAL and HIGH, warning on MEDIUM, and ignoring LOW.

Implementation uses Trivy’s exit code with the --severity flag. Add conditional logic in GitHub Actions to fail the workflow when Trivy returns a non-zero exit code. Then configure required status checks in your branch protection rules so PRs cannot merge until the check passes.

Here’s the setup in your repository settings:

  1. Go to Settings → Branches → Branch protection rules
  2. Add rule for your main branch
  3. Enable “Require status checks to pass before merging”
  4. Select “trivy-scan” from the list of status checks
  5. Enable “Require branches to be up to date before merging”

CVSS scoring provides a numerical score from 0.0 to 10.0 representing the technical severity of a vulnerability. Typical thresholds are 9.0-10.0 (critical), 7.0-8.9 (high), 4.0-6.9 (medium), and 0.1-3.9 (low).

Your organisational risk tolerance determines where to set the bar. Start with blocking CRITICAL and HIGH (CVSS >= 7.0) to establish security gates without overwhelming developers. Monitor false positive rate and triage burden, then refine thresholds over time.

CVSS reflects the maximum theoretical impact of a vulnerability in isolation. It’s global, static, and asset-agnostic. This is why reachability analysis adds value—it contextualises CVSS by showing whether the vulnerability is actually reachable in your application.

Notification integration improves workflow. Add a Slack webhook on failure to notify the security team. Generate a GitHub comment on the PR with scan results summary, CVE details, and suggested upgrade paths via Dependabot.

The developer experience matters. Provide clear remediation guidance in PR comments. Link to CVE details so developers understand the issue. Suggest specific upgrade paths rather than just flagging problems.

How to Set Up Automated Dependency Updates with Dependabot vs Renovate?

Automated remediation tools create pull requests to upgrade vulnerable dependencies without manual intervention. This reduces mean time to remediation (MTTR).

Dependabot is GitHub-native. Zero configuration required. It automatically detects vulnerable dependencies and creates individual PRs per upgrade.

Renovate is open-source with advanced features. It supports monorepos, grouped updates, custom upgrade strategies, and multi-platform deployment (GitHub, GitLab, Bitbucket).

Dependabot pros: native GitHub integration, simple setup (enable in repository settings), free for all repositories, broad ecosystem coverage.

Dependabot cons: limited configuration, individual PRs can spam notifications, no grouped updates, basic breaking change detection.

Renovate pros: sophisticated grouping rules, schedule control, automerge capabilities, better handling of major version upgrades, customisable PR templates.

Renovate cons: requires configuration file (renovate.json), more complex setup, learning curve for advanced features.

Decision framework: use Dependabot if you prioritise simplicity and native GitHub integration. Use Renovate if you’re managing monorepos or need custom upgrade strategies.

Dependabot setup is straightforward. Enable it in Security → Dependabot in your repository settings. Configure dependabot.yml to specify which package ecosystems to monitor.

Here’s an example dependabot.yml:

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5
    ignore:
      - dependency-name: "react"
        versions: ["17.x"]

Renovate setup requires adding a renovate.json configuration file to your repository. Configure grouping rules to batch related updates into single PRs. Set schedules for PR creation to avoid notification spam during working hours.

Here’s an example renovate.json:

{
  "extends": ["config:base"],
  "schedule": ["after 10pm every weekday", "before 5am every weekday"],
  "packageRules": [
    {
      "groupName": "dependencies",
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    }
  ],
  "prConcurrentLimit": 5
}

Can Dependabot and Renovate work together? Technically yes, but not recommended. You’ll get conflicting PRs and notification spam. Choose one based on your needs.

Use both tools in combination with Trivy. Trivy scans and blocks vulnerabilities at PR time. Dependabot or Renovate automatically creates PRs with fixes. This creates a closed loop: detection, notification, automated remediation.

Trivy vs Snyk: When to Use Free vs Paid SCA Tools?

Trivy is free and open-source. Snyk is commercial with advanced features like reachability analysis and a curated vulnerability database.

Trivy strengths: zero cost, fast scanning, container/IaC/file system support, SBOM generation, NVD vulnerability database, CLI flexibility.

Snyk offers a broad suite of application security features with its core strength being Software Composition Analysis. Snyk strengths: reachability analysis (80% false positive reduction), curated vulnerability data (faster updates than NVD), IDE integration, developer-friendly UI, automated fix suggestions.

Snyk pricing scales with team size. Snyk Free tier offers limited scans. Snyk Team costs $25-$98 per developer per month for 25-200 developers. Snyk Enterprise has custom pricing for teams over 200 developers.

Decision framework: use Trivy if you’re cost-conscious, your technical team is comfortable with CLI tools, and basic vulnerability detection is sufficient.

Upgrade to Snyk when alert fatigue becomes a problem (reachability needed), you need UI/IDE integration, or compliance requires enhanced SLA and support.

Migration path: start with Trivy to prove value. Collect metrics on false positive rate and time spent on triage. Evaluate Snyk when the cost of manual triage exceeds the cost of the tool.

Alternative consideration: Grype from Anchore offers similar features to Trivy with a different database update model. It’s worth evaluating if Trivy doesn’t fit your workflow.

How to Configure OWASP Dependency-Track for Continuous Monitoring?

OWASP Dependency-Track is an open-source platform that ingests SBOMs to provide continuous vulnerability monitoring beyond one-time CI/CD scans.

The difference from CI/CD scanning is important. CI/CD scans run when code changes. Dependency-Track monitors deployed applications for newly disclosed vulnerabilities. After deployment, if a new CVE is disclosed affecting your dependency, Dependency-Track alerts your security team even though the code hasn’t changed.

Setup process: deploy the Dependency-Track server using Docker Compose or Kubernetes. Create a project in the UI. Upload SBOMs via API or UI. Configure vulnerability sources (NVD, GitHub Advisories, Sonatype OSS Index, Snyk, Trivy, OSV).

Here’s a Docker Compose setup:

version: '3.7'

services:
  dtrack-apiserver:
    image: dependencytrack/apiserver
    environment:
      - ALPINE_DATABASE_MODE=external
      - ALPINE_DATABASE_URL=jdbc:postgresql://postgres:5432/dtrack
      - ALPINE_DATABASE_DRIVER=org.postgresql.Driver
      - ALPINE_DATABASE_USERNAME=dtrack
      - ALPINE_DATABASE_PASSWORD=changeme
    ports:
      - "8081:8080"
    depends_on:
      - postgres

  dtrack-frontend:
    image: dependencytrack/frontend
    environment:
      - API_BASE_URL=http://localhost:8081
    ports:
      - "8080:8080"

  postgres:
    image: postgres:13
    environment:
      - POSTGRES_DB=dtrack
      - POSTGRES_USER=dtrack
      - POSTGRES_PASSWORD=changeme
    volumes:
      - dtrack-data:/var/lib/postgresql/data

volumes:
  dtrack-data:

Integration with Trivy is straightforward. Generate an SBOM using the trivy sbom command in CycloneDX or SPDX format. For comprehensive automated SBOM creation in your CI/CD pipeline with cryptographic signing, you can integrate Syft alongside Trivy. Upload the SBOM to Dependency-Track via API in your GitHub Actions workflow.

Here’s the workflow addition:

- name: Generate SBOM
  run: |
    trivy sbom --format cyclonedx --output sbom.json .

- name: Upload SBOM to Dependency-Track
  run: |
    curl -X POST "http://dependency-track:8081/api/v1/bom" \
      -H "X-Api-Key: ${{ secrets.DTRACK_API_KEY }}" \
      -H "Content-Type: multipart/form-data" \
      -F "project=${{ secrets.DTRACK_PROJECT_UUID }}" \
      -F "[email protected]"

Configuration includes API keys for automated uploads, notification webhooks to Slack or email, severity-based alerting policies, and scheduled rescanning of existing SBOMs.

Benefits include a portfolio view across all projects, historical trending of vulnerability counts, policy-based alerts for new CVEs, and licence compliance tracking.

For CycloneDX vs SPDX: both are standardised SBOM formats. SPDX focuses on licensing and provenance, originally designed for open-source compliance. CycloneDX is security-focused with better vulnerability and dependency graph representation. For SCA use cases, CycloneDX is preferred.

FAQ

What are transitive dependencies and why are they risky?

Transitive dependencies are indirect dependencies (if A→B→C, then C is transitive). They’re risky because you don’t directly control their versions, and a vulnerability several layers deep can still affect your application.

Can Trivy detect licence compliance issues in dependencies?

Yes. Run trivy fs --scanners license to check licensing. Configure allowed and denied licence lists in your Trivy config. Integrate with OWASP Dependency-Track for ongoing licence compliance monitoring across projects.

How long does a Trivy scan take in a GitHub Actions pipeline?

Typical scan time is 30-90 seconds for a standard application with 50-200 dependencies. Optimise with caching, incremental scanning, and scan scheduling (use pull request triggers instead of every commit).

What happens when Trivy finds a vulnerability with no available fix?

When no patched version exists, you have three options:

  1. Accept the risk and document it in your security policy (if unexploitable or low severity).
  2. Remove or replace the vulnerable dependency with an alternative package.
  3. Apply a temporary ignore or suppression in Trivy config while monitoring for a patch release.

Create a .trivyignore file in your repository root listing CVE IDs to suppress. Add justification comments explaining why each CVE is ignored.

Here’s what a .trivyignore file looks like:

# CVE-2023-12345 - Vulnerability in unused test dependency
# Risk accepted: Code path not reachable in production
# Review date: 2024-06-01
CVE-2023-12345

# CVE-2023-67890 - Low severity XSS in admin panel
# Mitigated by: Network isolation and authentication requirements
# Review date: 2024-06-01
CVE-2023-67890

Does reachability analysis work for all programming languages?

No. Reachability analysis requires sophisticated static analysis capabilities that vary by language. Snyk supports reachability for Java, JavaScript/TypeScript, and Python. Other languages may have limited or no support. Trivy performs presence-based scanning and lacks native reachability analysis.

How do I handle false positives in Trivy scans?

Use a .trivyignore file to suppress known false positives. For systematic false positive reduction, consider upgrading to SCA tools with reachability analysis.

Can I use Trivy to scan private package registries?

Yes. Configure authentication for private registries using environment variables. Pass credentials securely via GitHub Actions secrets. Trivy supports authentication for npm, pip, Maven, Go modules, and other package managers.

Here’s how to set it up:

- name: Configure npm authentication
  run: |
    echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc

- name: Run Trivy with private registry access
  uses: aquasecurity/trivy-action@master
  env:
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    scan-type: 'fs'
    scan-ref: '.'

What’s the difference between SPDX and CycloneDX SBOM formats?

Both are standardised SBOM formats. SPDX emphasises licensing compliance and was originally designed for open-source compliance. CycloneDX focuses on security and vulnerability management, offering a lightweight approach optimised for identifying supply chain risks. For SCA use cases, CycloneDX is preferred.

How often should I update the Trivy vulnerability database?

Trivy’s database updates daily with new CVE disclosures from NVD and other sources. In CI/CD, use GitHub Actions caching with a 24-hour TTL to balance freshness against speed. For security-focused pipelines, update on every scan. For development environments, weekly updates are acceptable.

Can Dependabot and Renovate work together in the same repository?

Technically yes, but not recommended. You’ll get conflicting PRs and notification spam. Choose one based on your needs: Dependabot for simplicity and native GitHub integration, Renovate for advanced features like monorepo support and grouped updates.

What severity threshold should I use for PR blocking?

Start with blocking CRITICAL and HIGH (CVSS >= 7.0) to establish security gates without overwhelming developers. Adjust based on team velocity and risk tolerance. Monitor false positive rate and triage burden to refine thresholds. If a vulnerability is on CISA’s KEV catalog, it’s highest priority regardless of any other score.

How does Trivy compare to GitHub’s built-in Dependabot scanning?

Dependabot provides basic vulnerability scanning and automated PRs for fixes. It’s presence-based scanning without reachability. Trivy offers more control: severity thresholds, output formats, SBOM generation, faster database updates, and broader scanning (containers, IaC). Use both. Dependabot for automated remediation. Trivy for comprehensive CI/CD scanning and PR blocking.

Conclusion

Software Composition Analysis is just one element of comprehensive supply chain protection. You’ve learned how to implement Trivy for vulnerability scanning, configure PR-blocking workflows, integrate automated remediation, and decide when to upgrade to enterprise tools. For a complete understanding of how SCA fits into the broader context of regulatory compliance, SBOM generation, IDE security, and incident response, explore our supply chain security foundations guide.

AUTHOR

James A. Wondrasek James A. Wondrasek

SHARE ARTICLE

Share
Copy Link

Related Articles

Need a reliable team to help achieve your software goals?

Drop us a line! We'd love to discuss your project.

Offices
Sydney

SYDNEY

55 Pyrmont Bridge Road
Pyrmont, NSW, 2009
Australia

55 Pyrmont Bridge Road, Pyrmont, NSW, 2009, Australia

+61 2-8123-0997

Jakarta

JAKARTA

Plaza Indonesia, 5th Level Unit
E021AB
Jl. M.H. Thamrin Kav. 28-30
Jakarta 10350
Indonesia

Plaza Indonesia, 5th Level Unit E021AB, Jl. M.H. Thamrin Kav. 28-30, Jakarta 10350, Indonesia

+62 858-6514-9577

Bandung

BANDUNG

Jl. Banda No. 30
Bandung 40115
Indonesia

Jl. Banda No. 30, Bandung 40115, Indonesia

+62 858-6514-9577

Yogyakarta

YOGYAKARTA

Unit A & B
Jl. Prof. Herman Yohanes No.1125, Terban, Gondokusuman, Yogyakarta,
Daerah Istimewa Yogyakarta 55223
Indonesia

Unit A & B Jl. Prof. Herman Yohanes No.1125, Yogyakarta, Daerah Istimewa Yogyakarta 55223, Indonesia

+62 274-4539660