Appearance
Trivy — Vulnerability Scanning
Trivy is used in three distinct scan modes across the DevSecOps pipeline: dependency scanning, Infrastructure-as-Code scanning, and container image scanning. Together they cover the full supply chain from source packages to deployed containers.
Three Scan Modes
Pipeline Flow
─────────────────────────────────────────────────────
Stage 4: trivy fs → Scans dependency lockfiles
Stage 5: trivy config → Scans Bicep + YAML (IaC)
Stage 9: trivy image → Scans built container image
─────────────────────────────────────────────────────Severity Levels
Trivy uses a five-level severity model derived from CVSS scores and vendor advisories:
| Severity | CVSS Range | Color | Pipeline Action |
|---|---|---|---|
| CRITICAL | 9.0 – 10.0 | Red | Blocks (all modes) |
| HIGH | 7.0 – 8.9 | Orange | Blocks (IaC only) |
| MEDIUM | 4.0 – 6.9 | Yellow | Reported, no block |
| LOW | 0.1 – 3.9 | Blue | Reported, no block |
| UNKNOWN | — | Grey | Reported, no block |
Thresholds are configurable in DevSecOps/config/thresholds.yml.
Mode 1: Dependency Scanning (trivy fs)
Scans dependency manifest files and lockfiles without downloading packages. Supported ecosystems:
| Ecosystem | Files Scanned |
|---|---|
| .NET / NuGet | *.csproj, packages.lock.json |
| Node.js | package.json, package-lock.json, yarn.lock |
| Flutter / Dart | pubspec.yaml, pubspec.lock |
| Python | requirements.txt, Pipfile.lock, poetry.lock |
yaml
# Stage 4 pipeline task
- task: Bash@3
displayName: 'Stage 4 - Trivy Dependency Scan'
inputs:
script: |
trivy fs \
--scanners vuln \
--severity CRITICAL \
--exit-code 1 \
--format table \
--ignorefile $(Build.SourcesDirectory)/.trivyignore \
$(Build.SourcesDirectory)Trivy Config File (.trivy.yaml)
yaml
# .trivy.yaml — place in repository root
vulnerability:
type:
- os
- library
ignore-unfixed: false
severity:
- CRITICAL
- HIGH
- MEDIUM
cache:
dir: /tmp/trivy-cache
db:
no-progress: true
format: tableMode 2: IaC Scanning (trivy config)
Scans Infrastructure-as-Code files for misconfigurations. Applied to all files under Devops/azure/infrastructure/:
| File Type | What Is Checked |
|---|---|
| Bicep | Open inbound rules, missing diagnostics, unencrypted storage, public blob access |
| ARM JSON | Same as Bicep (converted) |
| Kubernetes YAML | Privileged containers, missing resource limits, hostPath volumes |
| Docker Compose | Privileged mode, bind mounts on sensitive paths |
yaml
# Stage 5 pipeline task
- task: Bash@3
displayName: 'Stage 5 - Trivy IaC Scan'
inputs:
script: |
trivy config \
--severity HIGH,CRITICAL \
--exit-code 1 \
--format table \
--tf-exclude-downloaded-modules \
--ignorefile $(Build.SourcesDirectory)/.trivyignore \
$(Build.SourcesDirectory)/Devops/azure/infrastructureCommon IaC Findings and Remediation
| Finding | Rule ID | Remediation |
|---|---|---|
| Storage blob public access | AVD-AZU-0008 | Set allowBlobPublicAccess: false |
| Key Vault no purge protection | AVD-AZU-0016 | Set enablePurgeProtection: true |
| CAE no managed identity | AVD-AZU-0130 | Assign user-assigned managed identity |
| SQL no TDE | AVD-AZU-0028 | Enable Transparent Data Encryption |
| Redis no SSL | AVD-AZU-0023 | Set enableNonSslPort: false |
Mode 3: Container Image Scanning (trivy image)
Scans the freshly built Docker image after Stage 8 (Docker Build) and before pushing to ACR:
yaml
# Stage 9 pipeline task
- task: Bash@3
displayName: 'Stage 9 - Trivy Image Scan'
inputs:
script: |
trivy image \
--severity CRITICAL \
--exit-code 1 \
--ignore-unfixed \
--format sarif \
--output $(Build.ArtifactStagingDirectory)/trivy-image.sarif \
--ignorefile $(Build.SourcesDirectory)/.trivyignore \
$(acrName).azurecr.io/$(imageName):$(Build.BuildId)The --ignore-unfixed flag skips CVEs that have no upstream fix available — these are tracked but not blocking.
SARIF Output
The SARIF report is uploaded to Azure DevOps Security tab for inline display:
yaml
- task: PublishBuildArtifacts@1
condition: always()
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)/trivy-image.sarif'
artifactName: 'security-trivy'.trivyignore — Accepted False Positives
The .trivyignore file lists CVE IDs that the security team has reviewed and accepted as false positives or non-exploitable in the Microtec context.
# .trivyignore
#
# Format: one CVE ID per line
# Each entry must have a comment above it with:
# - Date accepted
# - Reviewer name
# - Justification
# - Expiry date (must be re-reviewed before this date)
#
# ─────────────────────────────────────────────────────────
# Accepted: 2025-03-01 | Reviewer: M.Araby
# Justification: CVE affects Node.js CLI tooling only,
# not the Angular runtime bundle served to browsers.
# Expires: 2025-09-01 (re-review required)
CVE-2024-12345
# Accepted: 2025-04-10 | Reviewer: M.Araby
# Justification: CRITICAL in OpenSSL, but the affected function
# (X.509 certificate parsing) is not called by this service.
# Expires: 2025-10-01
CVE-2024-67890Policy:
.trivyignoreentries older than their expiry date will cause the pipeline to fail with a "stale ignore" error. Entries must be re-reviewed periodically.
SBOM Integration (Stage 10)
After Stage 9 image scan, Syft generates an SBOM from the same image. Trivy can also consume SBOMs for offline analysis:
bash
# Generate SBOM with Syft
syft $(imageName):$(tag) -o cyclonedx-json > sbom.cyclonedx.json
# Scan SBOM with Trivy (CI-independent, offline)
trivy sbom sbom.cyclonedx.json --severity CRITICAL,HIGHThreshold Configuration Reference
From DevSecOps/config/thresholds.yml:
yaml
trivy:
deps:
severity: CRITICAL # Block threshold for dependency scan
ignore_unfixed: false # Include unfixed vulnerabilities
iac:
severity: HIGH # Block threshold for IaC scan (HIGH+CRITICAL)
misconfig_scanners:
- azure
- dockerfile
image:
severity: CRITICAL # Block threshold for image scan
ignore_unfixed: true # Skip CVEs with no available fixRunning Trivy Locally
Developers can run Trivy locally to check their changes before pushing:
bash
# Install (macOS)
brew install aquasecurity/trivy/trivy
# Scan local directory for dependency vulns
trivy fs --severity CRITICAL,HIGH --scanners vuln .
# Scan IaC files
trivy config --severity HIGH,CRITICAL Devops/azure/infrastructure/
# Scan a local image
trivy image --severity CRITICAL myimage:latest
# Update vulnerability database
trivy image --download-db-onlyRelated Pages
- Pipeline Stages — Stage 4, 5, 9 details
- SBOM via Syft
- SonarCloud SAST