Install
openclaw skills install trivy-security-scannerRun Trivy vulnerability scans on containers, filesystems, and IaC — then triage findings by exploitability, reachability, and business impact with AI-powered prioritization.
openclaw skills install trivy-security-scannerRun Trivy scans against container images, filesystems, Git repositories, and Infrastructure-as-Code — then apply intelligent triage to cut through vulnerability noise. Instead of dumping 500 CVEs on your team, this skill prioritizes findings by exploitability (EPSS), reachability analysis, fix availability, and business context to produce an actionable remediation plan.
Use when: "scan this image for vulnerabilities", "run a security scan", "triage CVEs", "check for vulnerabilities in our dependencies", "container security audit", or when preparing for compliance reviews.
# Trivy installed
trivy version # 0.50+
# If not installed:
# Debian/Ubuntu
sudo apt-get install -y wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy
# macOS
brew install trivy
# Update vulnerability database
trivy image --download-db-only
Provide one or more scan targets:
nginx:1.25, ghcr.io/org/app:latest, or a local imageOptional parameters:
CRITICAL, HIGH, MEDIUM, LOW).trivyignore for accepted risksExample invocations:
Scan our production image
registry.example.com/api:v2.3.1and give me a prioritized remediation plan.
Run a filesystem scan on this project and tell me which vulnerabilities are actually reachable.
Scan all container images in our Kubernetes cluster and produce a compliance report for SOC2.
Run the appropriate Trivy scan type with JSON output for structured analysis:
Container image scan:
trivy image --format json --output /tmp/trivy-image.json \
--severity CRITICAL,HIGH,MEDIUM \
--vuln-type os,library \
--scanners vuln,secret,misconfig \
--list-all-pkgs \
registry.example.com/api:v2.3.1
Filesystem scan (project dependencies):
trivy fs --format json --output /tmp/trivy-fs.json \
--severity CRITICAL,HIGH,MEDIUM \
--scanners vuln,secret,misconfig,license \
--list-all-pkgs \
/path/to/project
IaC scan (Terraform, CloudFormation, Kubernetes manifests, Dockerfiles):
trivy config --format json --output /tmp/trivy-iac.json \
--severity CRITICAL,HIGH,MEDIUM \
/path/to/terraform
Kubernetes cluster scan: trivy k8s --format json --report all --severity CRITICAL,HIGH cluster
SBOM generation and scan: Generate with trivy image --format cyclonedx, then scan with trivy sbom --format json.
Parse the Trivy JSON output and extract structured vulnerability data:
# Extract vulnerability summary
cat /tmp/trivy-image.json | jq '{
target: .Results[].Target,
total_vulns: [.Results[].Vulnerabilities // [] | length] | add,
by_severity: [.Results[].Vulnerabilities // [] | .[]] | group_by(.Severity) |
map({severity: .[0].Severity, count: length}),
fixable: [.Results[].Vulnerabilities // [] | .[] | select(.FixedVersion)] | length,
unfixable: [.Results[].Vulnerabilities // [] | .[] | select(.FixedVersion == null)] | length
}'
Enrich each CVE with exploitability data to separate real threats from theoretical risks:
EPSS (Exploit Prediction Scoring System):
# Fetch EPSS scores for found CVEs
CVES=$(cat /tmp/trivy-image.json | jq -r '[.Results[].Vulnerabilities[]?.VulnerabilityID] | unique | join(",")')
curl -s "https://api.first.org/data/v1/epss?cve=$CVES" | jq '[.data[] | {
cve: .cve,
epss: .epss,
percentile: .percentile
}] | sort_by(-.epss)'
KEV (CISA Known Exploited Vulnerabilities):
# Check against CISA KEV catalog
curl -s https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json | \
jq --argjson cves "$(cat /tmp/trivy-image.json | jq '[.Results[].Vulnerabilities[]?.VulnerabilityID] | unique')" \
'[.vulnerabilities[] | select(.cveID as $id | $cves | index($id))]'
Triage classification:
| Category | Criteria | Action |
|---|---|---|
| Critical — Exploit in wild | In CISA KEV or EPSS > 0.5 | Fix within 24 hours |
| High — Likely exploitable | EPSS > 0.1, network-reachable | Fix within 1 week |
| Medium — Fix available | Has FixedVersion, EPSS < 0.1 | Fix in next sprint |
| Low — No fix / low risk | No fix, low EPSS, dev-only dep | Accept or monitor |
| Noise — False positive | Not reachable, test-only dep | Add to .trivyignore |
Determine whether vulnerable code is actually reachable in the application:
# Check if the vulnerable package is a direct or transitive dependency
# For Node.js:
npm ls <vulnerable-package> 2>/dev/null
# Check if it's a devDependency (not in production)
jq '.devDependencies["<package>"]' package.json
# For Python:
pip show <package> | grep -i "required-by"
# Check if it's in requirements-dev.txt only
grep -l "<package>" requirements*.txt
# For Go:
go mod why <module>
go mod graph | grep <module>
# For Java:
mvn dependency:tree -Dincludes=<groupId>:<artifactId>
Reachability factors the agent evaluates:
For each actionable finding, generate a specific remediation:
Dependency upgrades:
# Show exact version bumps needed
cat /tmp/trivy-image.json | jq '[.Results[].Vulnerabilities // [] | .[] |
select(.FixedVersion) | {
package: .PkgName,
installed: .InstalledVersion,
fixed: .FixedVersion,
cve: .VulnerabilityID,
severity: .Severity
}] | unique_by(.package) | sort_by(.Severity)'
Base image upgrade:
# Check if a newer base image fixes OS-level CVEs
trivy image --format json --severity CRITICAL,HIGH alpine:3.20 | \
jq '[.Results[].Vulnerabilities // []] | add | length'
Dockerfile hardening (from IaC scan findings):
# Before (insecure):
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
COPY . /app
CMD ["./app"]
# After (hardened):
FROM ubuntu:24.04 AS builder
RUN apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
COPY . /app
RUN ./build.sh
FROM gcr.io/distroless/base-debian12:nonroot
COPY --from=builder /app/binary /app/binary
USER 65532:65532
ENTRYPOINT ["/app/binary"]
Map findings to compliance framework controls:
SOC2 mapping:
:latest tagPCI-DSS mapping:
Generate or update the .trivyignore file for accepted risks:
# Format: CVE-ID with expiry and justification
# .trivyignore.yaml (preferred format)
vulnerabilities:
- id: CVE-2024-1234
paths:
- "usr/lib/libfoo.so"
expired_at: "2026-06-30"
statement: "Not reachable — library loaded but vulnerable function not called. Reviewed by @security-team on 2026-04-30."
- id: CVE-2024-5678
paths:
- "node_modules/dev-only-package"
expired_at: "2026-07-31"
statement: "Dev dependency only — not included in production image. No fix available upstream."
Suggest pipeline integration based on the project's CI system:
GitHub Actions:
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # Fail the build on findings
ignore-unfixed: true
trivyignores: '.trivyignore.yaml'
- name: Upload Trivy SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
The agent produces:
.trivyignore.yaml entries with justifications for findings that don't need fixingCVSS measures theoretical severity. EPSS measures actual exploitation probability. A CVSS 9.8 with EPSS 0.001 is less urgent than a CVSS 7.5 with EPSS 0.85 (actively exploited). This skill uses both: