Trivy Operator: Deep Dive
This document explains how vulnerability scanning works, what CVEs are, how Trivy scans container images, the VulnerabilityReport and ConfigAuditReport CRD structures, and how to build a security scanning pipeline for Kubernetes.
What Are CVEs?
Section titled “What Are CVEs?”CVE stands for Common Vulnerabilities and Exposures. It is a standardized naming system for publicly known security vulnerabilities. Each CVE entry has:
- CVE ID: A unique identifier like
CVE-2023-44487 - Description: What the vulnerability is and how it works
- Severity: CRITICAL, HIGH, MEDIUM, LOW, or UNKNOWN
- Affected packages: Which software versions are vulnerable
- Fixed version: The version that patches the vulnerability (if available)
- CVSS score: A numeric severity score from 0.0 to 10.0
CVEs are published by MITRE and tracked in databases maintained by organizations like the National Vulnerability Database (NVD) and GitHub Security Advisories.
How Vulnerability Scanning Works
Section titled “How Vulnerability Scanning Works”Vulnerability scanners analyze container images by:
- Extracting the image layers
- Reading the package manifest (dpkg, apk, rpm, pip, npm, etc.)
- Building a Software Bill of Materials (SBOM) listing all installed packages
- Comparing each package version against vulnerability databases
- Reporting any matches
For example, if an image contains openssl 1.1.1k and the database says CVE-2022-0778 affects versions below 1.1.1n, the scanner flags it.
Image Layers and Packages
Section titled “Image Layers and Packages”Container images are built in layers. Each layer represents a file system change:
FROM debian:11RUN apt-get update && apt-get install -y nginx=1.18.0COPY app.conf /etc/nginx/The scanner reads:
- Base layer: Debian 11 with all default packages
- Second layer: nginx 1.18.0 and its dependencies
- Third layer: Custom config file (no packages)
It extracts the full package list (libc6, libssl1.1, nginx, zlib1g, etc.) and checks each one.
Trivy Architecture
Section titled “Trivy Architecture”Trivy is a comprehensive security scanner that detects:
- OS package vulnerabilities (Alpine apk, Debian dpkg, RedHat rpm)
- Language dependencies (Python pip, Node npm, Ruby gem, Go modules)
- Misconfigurations (Kubernetes, Docker, Terraform)
- Secrets (API keys, passwords, tokens in files or environment variables)
- License compliance (GPL, MIT, Apache)
Trivy Database
Section titled “Trivy Database”Trivy maintains a vulnerability database synced from multiple sources:
| Source | Coverage |
|---|---|
| National Vulnerability Database (NVD) | All CVEs |
| Red Hat Security Data | RHEL, CentOS, Fedora |
| Debian Security Tracker | Debian, Ubuntu |
| Alpine SecDB | Alpine Linux |
| GitHub Advisory Database | npm, pip, RubyGems, Go, Rust |
| OSV (Open Source Vulnerabilities) | Aggregated source |
The database is updated daily. The Trivy Operator downloads it on startup and refreshes periodically.
Trivy Operator Components
Section titled “Trivy Operator Components”The Trivy Operator runs as a Kubernetes controller with these components:
1. Trivy Operator Deployment
Section titled “1. Trivy Operator Deployment”The main controller pod watches for:
- New pods created in the cluster
- Workload changes (Deployments, StatefulSets, DaemonSets, Jobs)
- ConfigMaps and Secrets for configuration scanning
- RBAC resources for role checks
When a pod is created, the operator reads the image references and triggers scans.
2. Trivy Scanner Pod
Section titled “2. Trivy Scanner Pod”For each scan, the operator spawns a Job that:
- Pulls the container image from the registry
- Runs the Trivy CLI to scan the image
- Writes results to a VulnerabilityReport CRD
- Deletes itself on completion
This isolates scanning from the control plane. The scanner pods run with minimal privileges.
3. Custom Resource Definitions (CRDs)
Section titled “3. Custom Resource Definitions (CRDs)”The operator creates several CRD types:
| CRD | Purpose |
|---|---|
| VulnerabilityReport | CVE findings for a container image |
| ConfigAuditReport | Kubernetes misconfiguration findings |
| ExposedSecretReport | Hardcoded secrets in images or configs |
| RbacAssessmentReport | RBAC role permission checks |
| InfraAssessmentReport | Cluster-level security checks |
| ClusterComplianceReport | CIS Benchmark compliance |
Each report is labeled with the workload name, namespace, and resource kind for filtering.
VulnerabilityReport Structure
Section titled “VulnerabilityReport Structure”Here is an example VulnerabilityReport for nginx:1.21:
apiVersion: aquasecurity.github.io/v1alpha1kind: VulnerabilityReportmetadata: name: replicaset-old-nginx-abc123-nginx namespace: trivy-demo labels: trivy-operator.resource.kind: ReplicaSet trivy-operator.resource.name: old-nginx-abc123 trivy-operator.container.name: nginxspec: image: repository: nginx tag: "1.21" registry: server: index.docker.io report: summary: criticalCount: 12 highCount: 34 mediumCount: 56 lowCount: 22 unknownCount: 3 vulnerabilities: - vulnerabilityID: CVE-2023-44487 resource: libnghttp2-14 installedVersion: 1.43.0-1 fixedVersion: 1.43.0-1+deb11u1 severity: CRITICAL title: "HTTP/2 Rapid Reset Attack" description: "The HTTP/2 protocol allows a denial of service..." links: - https://nvd.nist.gov/vuln/detail/CVE-2023-44487 score: 7.5 - vulnerabilityID: CVE-2023-4911 resource: libc6 installedVersion: 2.31-13+deb11u5 fixedVersion: 2.31-13+deb11u6 severity: HIGH title: "glibc buffer overflow in ld.so" primaryLink: https://nvd.nist.gov/vuln/detail/CVE-2023-4911 score: 7.8The report.vulnerabilities[] array contains all findings.
ConfigAuditReport Structure
Section titled “ConfigAuditReport Structure”This report checks Kubernetes resources against best practices:
apiVersion: aquasecurity.github.io/v1alpha1kind: ConfigAuditReportmetadata: name: replicaset-old-nginx-abc123 namespace: trivy-demospec: summary: criticalCount: 0 highCount: 2 mediumCount: 5 lowCount: 8 checks: - checkID: KSV001 title: "Process can elevate its own privileges" severity: MEDIUM category: "Pod Security Standards" description: "allowPrivilegeEscalation should be set to false" success: false messages: - "Container 'nginx' does not set allowPrivilegeEscalation to false" - checkID: KSV012 title: "Runs as root user" severity: HIGH category: "Pod Security Standards" description: "Containers should run as non-root user" success: false messages: - "Container 'nginx' is running as root (UID 0)" - checkID: KSV020 title: "No resource limits defined" severity: LOW category: "Resource Management" success: falseEach check references a control from the CIS Kubernetes Benchmark or Pod Security Standards.
Comparing Trivy vs Other Scanners
Section titled “Comparing Trivy vs Other Scanners”| Scanner | Strength | Weakness |
|---|---|---|
| Trivy | Fast, multi-language, free, easy to run | Database updates lag slightly behind NVD |
| Grype | Very fast, minimal dependencies | Fewer vulnerability sources than Trivy |
| Snyk | Great language support, dev tools integration | Commercial, expensive for large teams |
| Clair | Designed for registry integration | Harder to deploy, slower scans |
| Anchore | Policy enforcement, SBOM generation | Complex setup, resource-heavy |
All scanners work similarly (extract packages, compare to database). The differences are:
- Database sources: More sources mean better coverage but slower updates
- Speed: Grype is fastest, Clair is slowest
- Language support: Snyk and Trivy cover the most languages
- Kubernetes integration: Trivy Operator has the best native K8s support
Integrating Trivy into CI/CD
Section titled “Integrating Trivy into CI/CD”You can scan images before deploying them to catch vulnerabilities early. Two strategies:
1. Pre-deployment Scanning (CI)
Section titled “1. Pre-deployment Scanning (CI)”Run Trivy in your build pipeline:
# GitHub Actions example- name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: 'myapp:${{ github.sha }}' format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' exit-code: '1' # Fail the build if vulnerabilities foundThis prevents deploying vulnerable images.
2. Runtime Scanning (Trivy Operator)
Section titled “2. Runtime Scanning (Trivy Operator)”The operator scans what is actually running in the cluster. This catches:
- Images deployed before scanning was enabled
- New CVEs discovered after deployment
- Images pulled from untrusted registries
Best practice: Use both. Scan in CI to prevent deployment, and scan at runtime to catch drift.
Filtering and Ignoring CVEs
Section titled “Filtering and Ignoring CVEs”Sometimes you need to ignore false positives or accept risk. Trivy supports a .trivyignore file:
# Ignore this CVE because we use a patched kernelCVE-2023-1234
# Ignore all LOW severity findingsSEVERITY:LOW
# Ignore specific packagepkg:apk/alpine/busybox@1.35.0For the Trivy Operator, configure this in the Helm values:
trivy: ignoreUnfixed: true # Ignore CVEs with no fix available severity: CRITICAL,HIGH # Only report critical and highWhy Ignore Unfixed Vulnerabilities?
Section titled “Why Ignore Unfixed Vulnerabilities?”The demo uses --set trivy.ignoreUnfixed=true because some vulnerabilities have no patch yet. Reporting them creates noise without actionable fixes.
Example: A LOW severity CVE in a kernel package might have no fix for 6 months. If you scan a base image, you’ll see dozens of these. Filtering to only fixed vulnerabilities focuses on what you can act on.
VulnerabilityReport Retention
Section titled “VulnerabilityReport Retention”By default, Trivy Operator keeps reports forever. In large clusters, this creates thousands of CRDs. Configure TTL:
vulnerabilityReports: ttl: 24h # Delete reports older than 24 hoursReports are recreated when pods restart or images change.
RBAC for Trivy Operator
Section titled “RBAC for Trivy Operator”The operator needs permissions to:
- Watch pods, deployments, jobs, configmaps in all namespaces
- Create VulnerabilityReport and ConfigAuditReport CRDs
- Create scanner jobs in the trivy-system namespace
The Helm chart creates a ClusterRole with these permissions. Review it:
kubectl get clusterrole trivy-operator -o yamlSecurity Scanning vs Runtime Protection
Section titled “Security Scanning vs Runtime Protection”Trivy Operator scans for known vulnerabilities and misconfigurations. It does not protect against:
- Zero-day exploits (CVEs not yet in the database)
- Application logic bugs
- Runtime attacks (like process injection or network exfiltration)
For runtime protection, use tools like Falco, which detects suspicious behavior in running containers.
Further Resources
Section titled “Further Resources”- Trivy Documentation
- Trivy Operator GitHub
- NVD Database
- CIS Kubernetes Benchmark
- Pod Security Standards
Summary
Section titled “Summary”Trivy Operator continuously scans container images in your cluster and reports vulnerabilities via Kubernetes CRDs. It compares installed packages against a daily-updated CVE database and flags known security issues. Use it alongside CI scanning (pre-deployment) and runtime protection (Falco) for defense in depth.