Trivy: vulnerabilities and misconfiguration
Install Trivy Operator and light up three of the four security lenses — CVEs, misconfiguration, RBAC posture and the CIS benchmark.
Trivy Operator scans what is actually running: the CVEs in your images, workload misconfiguration, exposed secrets, RBAC posture and the CIS benchmark. Its findings land across the Vulnerabilities, Configuration, Permissions and Compliance lenses of Security & Compliance.
Nothing is pushed. Trivy writes CRDs and KubeBolt lists them on its sweep — no token, no webhook, no exposed endpoint.
Install
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
-n trivy-system --create-namespace \
--set="trivy.ignoreUnfixed=true"
ignoreUnfixed=true is a recommendation, not a requirement. A CVE with no
published fix is real, but it is not a task — there is nothing to upgrade to.
Turn it off when you need the full inventory for an audit, and expect the list
to grow a lot.
The CIS benchmark ships as a separate report on its own schedule. Nothing extra to install.
How KubeBolt finds it
By the label app.kubernetes.io/name=trivy-operator, falling back to pods
named trivy-operator* in the trivy-system, trivy-operator or security
namespaces. A hand-rolled manifest without the standard labels is still found
if it lives in one of those.
Verify
Reports appear a few minutes after install, one per workload:
kubectl get vulnerabilityreports -A
kubectl get configauditreports -A
kubectl get clustercompliancereports
| Symptom | Cause |
|---|---|
| Card says “not installed” | No pods matching the label or the fallback namespaces |
| Card says “degraded” | Operator pods present but not Ready |
| Reports exist, no CVEs in KubeBolt | They are all MEDIUM/LOW — see below |
| No reports after 10 minutes | The operator cannot pull images (private registry, no credentials) |
| CIS empty, everything else fine | The compliance report runs on its own schedule; give it a cycle |
What becomes a finding
CVEs: only CRITICAL and HIGH. MEDIUM and LOW are dropped on
purpose. On a busy cluster they are thousands of rows, and a list nobody can
finish is a list nobody reads. The full detail always stays in the reports
themselves.
Misconfiguration: CRITICAL, HIGH and MEDIUM. Wider than the CVE gate,
deliberately. Trivy’s MEDIUM band is where “runs as root”, “can escalate its
own privileges” and “seccomp disabled” live — several of those matter more than
things it calls HIGH. LOW is dropped: it is dominated by “runs with a high
UID” and “CPU/memory not limited”, and the latter is a capacity concern
KubeBolt already raises as an insight.
Compliance: only failing controls. A passing control produces nothing.
Exposed secrets are counted apart from CVEs, and they have no severity
gate: a LOW one is still a live credential in a layer anyone who can pull
the image can read. An unrecognised severity band is treated as HIGH. The
finding never contains the secret — Trivy’s partially masked match text is
not stored, only the file and the image — and the remediation says to rotate
the credential, not just remove it.
RBAC assessment: CRITICAL, HIGH and MEDIUM, the same gate as
misconfiguration, for both namespaced and cluster-wide roles.
Each CVE carries its remediation ready to act on — upgrade <pkg> <installed> → <fixed> — and the full image reference, rebuilt from the three fields
Trivy splits it across. That last part matters more than it looks: two
workloads sharing an image are one fix, and without the reference nothing
in the row says so.
The CIS rollup trap
Some CIS controls are not independent checks — they are sums of checks
KubeBolt already stores one by one. Any control whose checks are AVD-KSV-*
is evaluated from the same config-audit reports that already produced their own
findings.
Counting both would file the same problem twice: once as N workload misconfigurations, again as the control that groups them. Those controls are flagged as rollups, so the dashboard shows them as posture without adding them to the actionable total.
This was verified against a live cluster: for all 35 controls where both sides had data, the control’s own failing count equalled the summed failing results of exactly those checks. The duplication is arithmetic, not approximate.
Cost of the sweep. KubeBolt lists six report types per cluster, each a cluster-wide LIST across the agent tunnel. The cost tracks payload, not object count: measured on a dev cluster, 57 vulnerability reports took 110 ms while 120 config-audit reports took 29 ms — a vulnerability report carries hundreds of CVEs, an assessment report a handful of checks. If the sweep ever shows up in your latency, the lever is Trivy’s scan scope, not KubeBolt’s read.