Skip to content

ADR-0010: Add Trivy Dependency and Filesystem Scanning to CI

Metadata

Status: Accepted · Date: 2026-05-30 · Deciders: nguyenhuuca · Tags: security, devops
Related PRD: N/A · Supersedes: N/A · Superseded By: N/A

Tech Strategy: ✅ Follows Golden Path


Context

The CI pipeline covers build, test (coverage gate and SonarCloud), Docker build, and deploy. There is no automated vulnerability scanning of the container image or runtime dependencies before pushing to Docker Hub and deploying to production.

Two gaps were identified in the 2026-05-30 system health report: no container image scanning (MEDIUM severity) and no secrets scanning (MEDIUM severity). The JWT library at version 0.11.5 went undetected in CI for months and was only caught by manual review. Docker Hub and Kubernetes do not scan images automatically in this setup. The production image is based on eclipse-temurin:24-jre-alpine, which is minimal but still receives OS-level CVEs.


Decision Drivers

  • Vulnerable OS packages or transitive Java dependencies must be caught before reaching production
  • Scanning must integrate with GitHub Actions without requiring an external paid service
  • Pipeline overhead must remain acceptable (target: under 90 seconds per run)
  • Findings must be surfaced in a developer-visible interface (GitHub Security tab)
  • The gate policy must not block the release cadence on the first run before a baseline is established

Considered Options

Option 1: Trivy (Aqua Security) — chosen

Free, open-source scanner with a native GitHub Action; scans filesystem, container images, and secrets in one tool.

Pros Cons
Zero cost, OSS, maintained by Aqua Security Requires the Docker image to be built before image scanning can run
Native aquasecurity/trivy-action with SARIF output to GitHub Security tab Trivy DB is ~200MB per download (mitigated by caching)
Scans both filesystem and container image in one tool CRITICAL gate may cause false-positive blocks on first run
Fast (~30–60s on a warm runner)

Option 2: Snyk

Deep language-level scanning with fix suggestions.

Pros Cons
Detailed fix suggestions per vulnerability Full feature set requires a paid plan
Strong Java and Maven support External SaaS dependency; not self-contained in CI

Option 3: OWASP Dependency-Check

Maven plugin for Java dependency scanning.

Pros Cons
Java-focused, integrates as a Maven plugin Slow (~5 minutes per run)
No external service required Cannot scan container images
XML-only report; no native GitHub Security tab integration

Option 4: Dependabot

Automated pull requests for outdated dependencies.

Pros Cons
No pipeline overhead; runs asynchronously Reactive only; does not block deploys on vulnerabilities
Native GitHub integration Cannot scan container images
No active gate on severity

Option 5: Grype (Anchore)

Open-source scanner similar to Trivy with strong SBOM support.

Pros Cons
Good SBOM generation capability Less GitHub Actions ecosystem adoption than Trivy
Similar feature set to Trivy SARIF integration less mature

Decision Outcome

Chosen Option: Option 1 — Trivy Rationale: Trivy is zero-cost, actively maintained by Aqua Security, and has the widest adoption in GitHub Actions environments. It scans both filesystem and container image in one tool, eliminating the need for a separate Maven plugin. Its SARIF output integrates natively with the GitHub Security tab. At 30–60 seconds on a warm runner it does not meaningfully slow the pipeline. Snyk was excluded due to cost. OWASP Dependency-Check was excluded for speed and lack of image scanning. Dependabot was excluded for being reactive with no gate. Grype was excluded due to lower ecosystem adoption.

The scan target is the filesystem (api/ directory), catching CVEs in Maven dependencies declared in pom.xml and compiled JARs. Docker image scanning is deferred until Docker is used in the production deployment path.

Gate policy: fail on CRITICAL severity; HIGH severity is reported but non-blocking initially, to be tightened after a clean baseline is established. SARIF reports are uploaded to the GitHub Security tab on every run.

Quantified Impact (where applicable)

Metric Before After Notes
Pipeline duration Baseline +~60s On a warm runner with Trivy DB cached
Trivy DB download N/A ~200MB Mitigated by GitHub Actions cache
CVE visibility Manual review only Automated on every push SARIF surfaced in GitHub Security tab

Consequences

Positive: - Automated CVE detection runs before every production deploy - SARIF upload surfaces findings in GitHub Security Code Scanning tab - Catches both OS-level (Alpine) and Java library vulnerabilities in one job - Establishes the foundation for secrets scanning (--scanners secret can be added later)

Negative: - Pipeline gains one additional job (~60s on a warm runner) - Trivy DB must be downloaded each run if the cache is cold (~200MB)

Risks: - The CRITICAL gate may block the pipeline on the first run if existing dependencies carry unresolved critical CVEs; a one-time triage pass is required before the gate is activated - HIGH severity findings are non-blocking initially; if the threshold is not tightened after the baseline is established, medium-term risk accumulates - Image scanning is deferred; OS-level CVEs in the deployed container will not be caught until Docker is used in production


Validation

  • [x] Tech Strategy alignment confirmed
  • [ ] Related plan document created: docs/plans/plan-trivy-scan.md

  • System Health Report 2026-05-30 — source of MEDIUM priority gaps that triggered this ADR
  • ADR-0002 — CI/CD pipeline architecture
  • docs/plans/plan-trivy-scan.md — implementation plan
  • .github/workflows/funnyapp-ci.yml — target file for implementation

Changelog

Date Author Change
2026-05-30 nguyenhuuca Initial draft
2026-05-31 nguyenhuuca Restructured to new ADR template