CVE Vulnerability Scanning

Integrate CVE vulnerability scanning into your build pipeline to detect and remediate security vulnerabilities in container images and application dependencies.


Quick Start

Scan for vulnerabilities immediately after building the SBOM:

strata build run -f deploy.yaml --audit

This command:

  1. Builds platform artifacts and generates the SBOM

  2. Scans all dependencies and container images for known CVEs

  3. Reports findings with severity levels (CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN)

  4. Enforces the cve_max_severity policy (default: block builds if CRITICAL/HIGH found)

  5. Stores audit results in the deployment manifest


Overview

strata integrates CVE scanning at build time to catch vulnerabilities before deployment. The scanner analyzes:

  • Container images β€” Docker image references from modules and services

  • Application dependencies β€” NPM, PyPI, Maven, Ruby gems, Rust crates, Go modules, PHP Composer, .NET NuGet

  • Infrastructure components β€” Terraform providers, Helm charts, Ansible collections

Scan results are:

  • Linked to the SBOM β€” Each CVE references the specific component

  • Stored in manifests β€” Audit trail for compliance

  • Filterable β€” Allowlist false positives and accepted risks

  • Reportable β€” Console, VEX, and SARIF formats for integration with compliance tools


Backends

strata automatically detects and uses available CVE scanning backends in order of preference:

Backend

Detection

Speed

Scope

Best for

Trivy

Finds trivy on PATH

Fast (local)

Container images + dependencies

Default choice; no external deps

Grype

Falls back if Trivy absent

Fast (local)

Container images + dependencies

Fallback when Trivy unavailable

Installing Scanners

Both scanners are optional and auto-detected. Install as needed:

Trivy (recommended):

# macOS
brew install trivy

# Linux
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/trivy.list
apt-get update && apt-get install trivy

# Windows
choco install trivy

Grype (fallback):

# macOS
brew install grype

# Linux & Windows
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

Check Scanner Availability

strata tools status

Output shows which scanners are available:

  CVE Scanner     OK  trivy 0.46.0    (detected scanner)

Scanning with --audit

Basic Scan

strata build run -f deploy.yaml --audit

Fails the build if CRITICAL or HIGH severity CVEs are found (default policy).

Filter by Severity

strata build run -f deploy.yaml --audit --severity MEDIUM

Only reports vulnerabilities at MEDIUM severity or higher. Thresholds:

  • CRITICAL β€” Show only critical vulns

  • HIGH β€” Show high and critical

  • MEDIUM β€” Show medium, high, critical

  • LOW β€” Show low, medium, high, critical

  • UNKNOWN β€” Show all including unknown severity

Generate Reports

Export findings in structured formats:

# VEX (Vulnerability Exploitability Exchange)
strata build run -f deploy.yaml --audit --audit-report vex

# SARIF (Static Analysis Results Interchange Format)
strata build run -f deploy.yaml --audit --audit-report sarif

# Both
strata build run -f deploy.yaml --audit --audit-report vex,sarif

Report files are written to the build directory alongside the SBOM:

.strata/build/prod-1.0.0/
β”œβ”€β”€ platform.json
β”œβ”€β”€ sbom.json
β”œβ”€β”€ sbom-audit.json          ← CVE audit result
β”œβ”€β”€ sbom.vex.json            ← VEX report (if --audit-report vex)
└── sbom.sarif.json          ← SARIF report (if --audit-report sarif)

SARIF is ideal for:

  • Integration with GitHub Security tab

  • Integration with code review tools

  • CI/CD pipeline result aggregation

VEX is ideal for:

  • NTIA Software Supply Chain visibility

  • Component status tracking (vulnerable, unaffected, fixed)

  • Compliance evidence


Allowlist: Ignore Known Issues

False positives or accepted risks can be suppressed using .strata/cve-allowed.yaml:

Create an Allowlist

# .strata/cve-allowed.yaml

allowed:
  # Suppress a specific CVE globally
  - id: CVE-2024-1234
    reason: "Requires local attacker with shell access; not exploitable in our deployment model"
    package: optional-package-name  # Optional: scope to specific package
    expires: "2026-12-31"           # Optional: automatically re-enable after date

  # Suppress another
  - id: CVE-2024-5678
    reason: "Patch released; upgrade scheduled for next sprint"
    expires: "2026-08-15"

  # Package-specific
  - id: CVE-2024-9999
    reason: "Transitive dependency; plan to remove in next major version"
    package: some-library

How Allowlists Work

  1. Matching β€” CVE ID + package name (optional) must match

  2. Expiration β€” Entries with expired dates are ignored (CVE re-reported)

  3. Logging β€” Suppressed CVEs are logged as warnings (visible with --verbose)

  4. Audit trail β€” Suppressed findings are still recorded in the manifest for compliance

Example workflow:

# First scan: finds CVE-2024-1234 in library-X
strata build run -f deploy.yaml --audit
# Fails: CRITICAL CVE-2024-1234

# Add to allowlist with justification
# (edit .strata/cve-allowed.yaml)

# Second scan: CVE is suppressed
strata build run -f deploy.yaml --audit
# Succeeds (with warning about suppressed CVE)

# Audit export includes both real + suppressed findings
strata audit export --include-audit

Policy: cve_max_severity

The cve_max_severity policy enforces a maximum acceptable severity level. If any vulnerability meets or exceeds the threshold, the build can fail, warn, or just audit.

Default Behavior

By default, the policy is loaded from the workspace configuration and enforces:

  • CRITICAL or HIGH β†’ Fail build (enforcement: deny)

  • MEDIUM β†’ Warn in logs (enforcement: warn)

  • LOW or UNKNOWN β†’ Audit only (enforcement: audit)

Configure in Workspace YAML

Override defaults in your workspace configuration:

# config/workspace.yaml

policies:
  - name: cve_max_severity
    type: cve_max_severity
    enabled: true
    max_severity: HIGH          # Fail on HIGH or higher
    enforce_on: ["deployment"]  # Which deployment types
    enforcement: deny           # Action: deny|warn|audit

Enforcement Levels

Level

Behavior

Use Case

deny

Fail the build with exit code 1

Production: block known vulns

warn

Log warning; build succeeds

Development: alert but don’t block

audit

Record only in manifest

Compliance: track all findings

Disable the Policy

To skip vulnerability checks:

strata build run -f deploy.yaml --audit --no-policy cve_max_severity

Or set enabled: false in the workspace policy config.


Understanding CVE Results

Console Output

After scanning, you’ll see:

πŸ” CVE Audit Result
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Scanner       : trivy 0.46.0
  SBOM          : .strata/build/prod-1.0.0/sbom.json
  Findings      : 7 total
  
  CRITICAL  : 1     ⚠️  Policy: deny (build failed)
  HIGH      : 2
  MEDIUM    : 3
  LOW       : 1
  UNKNOWN   : 0

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

CVE Finding Fields

Each finding includes:

Field

Example

Meaning

vulnerability_id

CVE-2024-1234

Official CVE identifier

severity

CRITICAL

Severity level

package_name

openssl

Affected package

installed_version

1.0.1e

Currently deployed version

fixed_version

1.0.1w

Version that fixes the vuln

title

β€œTLS heartbeat read overflow”

Short description

purl

pkg:npm/express@4.18.0

Package URL

JSON Audit Result

The sbom-audit.json file contains all findings:

{
  "scanner": "trivy",
  "scanner_version": "0.46.0",
  "sbom_path": ".strata/build/prod-1.0.0/sbom.json",
  "total_findings": 7,
  "critical": 1,
  "high": 2,
  "medium": 3,
  "low": 1,
  "unknown": 0,
  "findings": [
    {
      "vulnerability_id": "CVE-2024-1234",
      "severity": "CRITICAL",
      "package_name": "openssl",
      "installed_version": "1.0.1e",
      "fixed_version": "1.0.1w",
      "title": "TLS heartbeat read overflow",
      "purl": "pkg:generic/openssl@1.0.1e"
    },
    ...
  ]
}

Remediation

When vulnerabilities are found, take action:

1. Update to Fixed Version

For package vulnerabilities:

# Update in your application dependency file
npm install openssl@1.0.1w
pip install openssl==1.0.1w
go get -u github.com/some/package@v1.2.3

# Rebuild the SBOM and rescan
strata build run -f deploy.yaml --audit

For container image vulnerabilities:

# Update base image in Dockerfile
FROM node:18.17.1  # ← More recent version with patched deps

2. Suppress with Allowlist (Temporary)

If a fix isn’t immediately available:

# .strata/cve-allowed.yaml
allowed:
  - id: CVE-2024-1234
    reason: "Fix available in v2.0; upgrade planned for sprint 12"
    expires: "2026-08-01"

3. Use Vulnerability Data

Export to compliance tools:

# VEX report for supply chain visibility
strata build run -f deploy.yaml --audit --audit-report vex
# Upload sbom.vex.json to supply chain tool

# SARIF for GitHub
strata build run -f deploy.yaml --audit --audit-report sarif
# GitHub Actions: Upload sarif file with SARIF upload action

SBOM Integration

CVE results are automatically linked to the SBOM:

# Generate SBOM with CVE scan
strata build sbom -f deploy.yaml --audit

# Result: sbom.json + sbom-audit.json created

Each component in the SBOM is cross-referenced with the audit results:

{
  "components": [
    {
      "type": "library",
      "name": "openssl",
      "version": "1.0.1e",
      "purl": "pkg:generic/openssl@1.0.1e"
      // In sbom-audit.json, look for findings with matching purl
    }
  ],
  "services": [
    {
      "name": "web",
      "image": "node:18.16.0",
      "purl": "pkg:docker/library/node@18.16.0"
      // Scan results for this image available in sbom-audit.json
    }
  ]
}

Use this mapping to understand which CVEs affect which parts of your deployment.


Deployment Manifests

Vulnerability scan results are captured in deployment manifests:

strata build run -f deploy.yaml --audit

# Manifest contains:
# - scanner backend (trivy/grype)
# - scan timestamp
# - total findings count by severity
# - CVE audit result path
# - Policy enforcement decision

Export manifests for audit evidence:

strata audit export --include-manifests

# Output includes:
# manifests/
# β”œβ”€β”€ prod-1.0.0-manifest.json  ← Contains CVE audit reference
# β”œβ”€β”€ sbom.json
# β”œβ”€β”€ sbom-audit.json
# └── sbom.vex.json

CI/CD Integration

GitHub Actions

name: Build with CVE Scan

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Install strata
        run: pip install strata-cli
      
      - name: Install Trivy
        run: brew install trivy
      
      - name: Build with CVE scan
        run: strata build run -f deploy.yaml --audit --audit-report sarif
      
      - name: Upload SARIF results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: .strata/build/*/sbom.sarif.json
      
      - name: Fail if critical vulns
        if: failure()  # If build failed due to CVE policy
        run: exit 1

GitLab CI

build_with_cve_scan:
  image: python:3.13
  script:
    - pip install strata-cli
    - apt-get update && apt-get install -y trivy
    - strata build run -f deploy.yaml --audit --audit-report sarif
  artifacts:
    reports:
      sast: .strata/build/*/sbom.sarif.json
  allow_failure: false  # Fail on vulns

Generic CI (exit code check)

#!/bin/bash
set -e

# Build with CVE scan
strata build run -f deploy.yaml --audit --audit-report vex

# Collect results
cp .strata/build/*/sbom*.json ./build-output/

# Upload to compliance system
curl -X POST https://compliance-system/upload \
  -F "vex=@./build-output/sbom.vex.json" \
  -F "audit=@./build-output/sbom-audit.json"

Troubleshooting

No Scanner Found

Error: No CVE scanner backend detected (trivy and grype not found)

Solution: Install Trivy or Grype (see β€œInstalling Scanners” above).

strata tools status  # Check what's available

Scan Takes Too Long

Solution: The first scan downloads the vulnerability database. Subsequent scans use the cache:

# First scan: ~1-2 minutes (downloads DB)
strata build run -f deploy.yaml --audit

# Second scan: ~10-30 seconds (uses cache)
strata build run -f deploy.yaml --audit

To clear the cache (force fresh DB):

trivy image --download-db-only --refresh

False Positives in Allowlist Not Working

Check the CVE ID and package name:

# Incorrect (won't match)
- id: CVE-2024-1234
  package: "openssl"    # ← Package name must match SBOM component name exactly

# Check SBOM to see exact names
strata build sbom -f deploy.yaml
# View .strata/build/*/sbom.json and search for package names

Policy Blocking Build, Need to Investigate

# Build with warnings only (no failure)
strata build run -f deploy.yaml --audit --no-policy cve_max_severity

# See all findings
strata build run -f deploy.yaml --audit --severity UNKNOWN --verbose

# Export detailed report
strata build run -f deploy.yaml --audit --audit-report vex,sarif

# View results
cat .strata/build/*/sbom-audit.json | jq '.findings | .[].vulnerability_id'

See Also