• self-hosting
  • open source
  • comparisons
  • Kubernetes

Self-hosted vulnerability management for Kubernetes: the open-source options, and what each one makes you run

Trivy Operator, Kubescape, Harbor, Dependency-Track, DefectDojo, a CronJob and StackRadar CE: what each stores, what you must run, and when to pick it.

StackRadar Team

12 min read

If your images all pass through a registry you run, Harbor scans them where they sit. If you want posture checks and nothing to install but an operator, Trivy Operator or Kubescape. If CI already produces SBOMs and you want a place that re-evaluates them, Dependency-Track. If you have five scanners and need one queue, DefectDojo. If the question is "what is running in this cluster, what landed on it this week, and what do we fix first", with history, EPSS and KEV, and one Helm command, StackRadar Community Edition. Each one keeps your data inside your network, and each one makes you run something.

This is the companion to our roundup of open-source scanners. That post is about finding vulnerabilities; this one is about keeping them: where the results live, what happens to them when the next advisory lands, and what you sign up to operate. It names the tool that does each job best, including where that is not us.

What "vulnerability management" has to do that scanning does not

A scanner takes an image and returns a list. Management is what makes that list useful a week later, and it is four separate jobs:

  • Inventory what actually runs. Not the manifests, not the registry: the image digests the kubelets report, per pod, including sidecars and init containers. The manifests cannot answer this.
  • Keep the findings, with history. So "was this critical here last month" and "what changed since the deploy" are queries, not forensics.
  • Re-evaluate without rescanning. An image's contents never change; the advisories do. A tool that only knows what was true at scan time needs a new scan for every new CVE.
  • Rank and route. CVSS alone produces thousands of criticals; EPSS and KEV turn them into a list a team can work, and the owner of each finding has to be findable from it.

"Self-hosted" adds a fifth: every one of those jobs runs on infrastructure you operate, which means a database you back up, advisory feeds you mirror or allow through egress, and upgrades you schedule. The table below is scored on the four jobs plus that cost.

The short version

OptionInventories running imagesKeeps historyRe-matches stored SBOMsRanks beyond CVSSYou runLicence
Trivy OperatorYesNo, reports expire and regenerateNo, rescansNoOne operator; reports live in etcdApache-2.0
Kubescape operatorYesLimited in-cluster; full on the vendor platformNoRuntime relevancy in-cluster; EPSS and KEV on the platformOperator, node agent, its own storage componentApache-2.0 (platform closed)
HarborNo, scans what is pushedPer artefact, yesRescans on scheduleNoA registry: Postgres, Redis, storage, and the Trivy adapterApache-2.0
Dependency-TrackNo, you upload SBOMsYesYesEPSS; KEV in policiesAPI server, frontend, Postgres, feed mirrors; the SBOM pipelineApache-2.0
DefectDojoNo, you import reportsYesNo, re-importSLAs and risk acceptance; no EPSS or KEV of its ownDjango app, Postgres, a broker and workers; the scanners that feed itBSD-3-Clause
A CronJob and a bucketYesFiles per runYes, if the script doesWhatever you join inA CronJob, a bucket, your scriptYours
StackRadar Community EditionYesYesYes, hourly mirrorCVSS, EPSS and KEV in one scoreOne Helm release: server, dashboard, scanner, Postgres; one clusterAGPL-3.0 (scanner and chart Apache-2.0)

Trivy Operator: the scanner, kept in the cluster

The operator watches workloads, runs Trivy against each image, and writes a VulnerabilityReport per workload as a custom resource, plus configuration audits, RBAC assessments and exposed-secret reports that nothing else on this page does. Nothing to run but the operator, and kubectl get vulnerabilityreports is the interface. It is the right first install for most clusters and it is what we tell people to run next to StackRadar for the configuration side.

As a management layer it has two limits that are design, not bugs. Reports are regenerated on a TTL, 24 hours by default, so there is no history and no diff: a finding that was there yesterday and is gone today left no trace. And the reports are objects in etcd, which on a large cluster is a real operational problem; the fix the project offers is to turn the SBOM reports off. If you keep Trivy Operator for management rather than detection, you end up exporting the CRDs to something with a database, and that something is the rest of this list. The compare page has the row-by-row version.

Kubescape: posture first, with image scanning attached

Kubescape's operator does configuration scanning against NSA, MITRE and CIS frameworks, image vulnerability scanning with Grype underneath, and, with its eBPF node agent, a "relevancy" signal that marks which vulnerable packages were actually loaded by a running process. That last part is unique in the open-source tier and is a genuinely better filter than severity for a cluster you cannot patch quickly. Results go to its own storage component rather than etcd, which avoids Trivy Operator's problem.

History, EPSS, KEV and the multi-cluster view live on ARMO's platform, which is the closed product the open-source operator feeds; in-cluster you get the current state and the relevancy data. Choose it when posture is the bigger problem and the vulnerability list is secondary; the comparison says where it and StackRadar overlap and where they do not.

Harbor: scan at the registry

If every image your clusters run is pushed to or proxied through a registry you operate, the simplest self-hosted vulnerability management is in the registry. Harbor, a CNCF graduated project, ships with Trivy as its default scanner, scans each artefact on push and on a schedule you set, keeps the result per artefact with its history, and can block pulls of images above a severity. The operations are the registry's: Postgres, Redis, object or block storage, and the scanner adapter.

What it does not know is what is running. An image pushed six months ago and never deployed is scanned as diligently as the one in production, and an image a pod pulled straight from Docker Hub is not scanned at all unless the pull went through a Harbor proxy cache. Registry-side scanning is the right answer for "is anything bad in our supply", and it has no answer for "is anything bad running". Many teams run it and one of the in-cluster tools together.

Dependency-Track: the SBOM platform

OWASP Dependency-Track is the original of the model StackRadar uses: send it a CycloneDX SBOM per thing you ship, it keeps the SBOM, and it re-evaluates every stored component against the NVD, OSV, GitHub advisories and the rest as those feeds change, continuously, without you re-uploading anything. It has EPSS, KEV-aware policies, a policy engine that can fail a build, and a decade of production use behind it. For SBOMs that cover more than containers, from vendors, firmware or desktop builds, there is nothing better in the open-source tier.

It does not make SBOMs and it does not know Kubernetes. A project is whatever you named it; nothing attaches a namespace, a workload or a Helm release to a finding, and nothing notices that a pod moved to a new digest. So the pipeline that discovers running images, generates one SBOM per digest and keeps the projects current is yours to build and run, and that pipeline is most of the work. The operations are an API server, a frontend, Postgres and the feed mirrors, with a one-way migration between its major versions. The compare page goes into the overlap with StackRadar, which is large.

DefectDojo: one queue for every scanner

OWASP DefectDojo does not scan anything. It imports the reports of well over a hundred tools, Trivy and Grype among them, deduplicates across them, attaches SLAs, risk acceptances and Jira tickets, and gives an application security team one place to work from. If your problem is that container findings, SAST findings and pentest findings arrive in five formats and nobody owns the merge, this is the tool, and nothing else on this page is trying to be it.

For the Kubernetes case specifically it is a consumer, not a source: it knows what you imported, when you imported it, and does not re-evaluate old imports against new advisories, so the freshness of its container data is the freshness of the scan job that feeds it. It is a Django application with Postgres, a message broker and worker processes, and its own release cadence to keep up with.

A CronJob and a bucket: the honest minimum

One scheduled job with a read-only ServiceAccount lists the running digests, generates an SBOM once per digest, matches each SBOM against today's database and writes both to a bucket. We published the whole thing: the Dockerfile, the manifests and the script, about two hundred lines. It inventories what runs, it keeps history as dated files, it re-matches because the SBOMs are kept and the match step runs daily, and it ranks however you join the EPSS and KEV feeds in. It puts nothing in etcd and needs no database.

What it does not have is a reader. Answering "which pods carry this CVE" is a jq query over the bucket; answering it for someone who does not have the bucket is a Slack message from whoever does. That is fine for one cluster and one platform engineer and it stops being fine at the second team. It is also the closest thing to a precise description of what StackRadar's scanner and server do, with a UI, a database and a mirror in place of the bucket and the cron.

StackRadar Community Edition: the running cluster, with history and a score

Since 17 October 2026 the whole of StackRadar is on GitHub, and the community edition is the same server and dashboard that run our cloud, booted as the dashboard for the one cluster it is installed in. One Helm release installs the server, the dashboard, a bundled Postgres and the scanner:

helm
helm install stackradar \
  oci://ghcr.io/lockdep/helm-charts/stackradar \
  --namespace stackradar --create-namespace
kubectl -n stackradar port-forward svc/stackradar-client 3000:3000

What you get against the four jobs: the scanner is a read-only agent that watches the pods of its cluster and builds one SBOM per running image digest with Syft, so the inventory is what the kubelets report and nothing is written to etcd. The server keeps every SBOM and every finding with history, and mirrors OSV.dev hourly and EPSS and KEV daily, re-matching every stored SBOM when the mirror changes, so a new advisory shows up on the images that carry it without a rescan. Every finding is scored with CVSS, EPSS and KEV folded into one number, summed per image, container, Helm release and cluster, and carries the namespace, workload, chart and Argo CD application it came from. New critical and KEV findings can go to a Slack webhook. Sign-in is local accounts, any OpenID Connect provider, GitHub or Google. There is no telemetry; the only outbound traffic is the three advisory feeds.

What you run: Kubernetes 1.25 or newer, and one Postgres. The default install mirrors the ecosystems that cover mainstream base images and language packages, which downloads about 1.2 GB compressed and needs up to about 2 GB of memory on the server while it imports; the bundled Postgres volume defaults to 10 GiB, and mirroring the entire OSV corpus instead takes about 12 GB. The bundled Postgres is single-node and yours to back up and upgrade, or you point the chart at one you already run. The manual in the repository covers the real Helm install and its fixture credentials to replace, OIDC, users, upgrading and backups, and the self-hosting page here is the door to it.

The limits, so nobody reads this as a clean sweep: the community edition is one cluster per install, with no fleet view; it does no configuration or RBAC scanning, so Trivy Operator or Kubescape still earn their place beside it; and it only knows what OSV knows, which leaves some distributions and some compiled binaries uncovered. The licence is AGPL-3.0 for the server and dashboard, Apache-2.0 for the scanner and the chart, and the README's table lists what only the cloud edition does.

Choosing

  • You own the registry and want the least new infrastructure: Harbor, and accept that it measures the supply, not the runtime.
  • You need configuration and RBAC findings as much as CVEs: Trivy Operator or Kubescape, and export the results somewhere with a database before you need history.
  • Your SBOMs already exist and cover more than containers: Dependency-Track, and budget for the pipeline that keeps its projects matching your clusters.
  • You have many scanners and one security team: DefectDojo, fed by one of the others.
  • One cluster, one engineer, zero budget: the CronJob, and come back when a second team asks for the bucket.
  • You want the running cluster, with history, EPSS and KEV ordering and the Helm release on every finding, in one install: StackRadar Community Edition, and keep Trivy Operator for the posture side.

Whichever you pick, the self-hosting work is the same shape: one database to back up, feeds to let through or mirror, upgrades to read the notes for. The tools differ in how much of the four jobs they do before you start writing glue, and that, more than the licence, is what the choice is about.

Frequently asked questions

Can I run any of these fully air-gapped?

Every tool on this page needs advisory data from outside, so "air-gapped" means "with a mirror you feed". Trivy and Grype publish their databases as OCI artifacts you can copy into a private registry; Harbor and Trivy Operator consume them from there. Dependency-Track can be pointed at mirrored NVD and OSV data. StackRadar Community Edition fetches OSV.dev, the EPSS feed and the CISA KEV catalogue over HTTPS from the server itself and, as of October 2026, has no offline feed bundle, so it needs those three endpoints reachable through a proxy or an egress allowlist; the scanner needs only its registries and the server.

Is Trivy Operator enough on its own?

For finding out what is vulnerable right now in one cluster, yes, and it adds configuration and RBAC checks none of the others have. It is not vulnerability management: reports are regenerated rather than kept, so there is no history, findings carry CVSS severity only, and nothing re-evaluates an old report when a new advisory lands. Teams usually pair it with a store, which is where the rest of this list comes in.

Dependency-Track or StackRadar Community Edition?

They share the core idea: keep the SBOM, re-match it as advisories change. Dependency-Track is the better choice when your SBOMs come from CI or from vendors, cover more than containers, and you want its policy engine; you build the pipeline that generates and uploads them. StackRadar is the better choice when the inventory you care about is what the kubelets are running and you want the SBOMs generated for you, with the namespace, workload and Helm release on every finding. There is a longer comparison at /compare/dependency-track.

What does self-hosting StackRadar cost in resources?

A Kubernetes 1.25 or newer cluster and Helm 3.8 or newer. The server needs up to about 2 GB of memory while it imports the OSV mirror for the default ecosystem list, which downloads about 1.2 GB compressed; the bundled Postgres volume defaults to 10 GiB. Mirroring the entire OSV corpus instead takes about 12 GB of Postgres and 2.5 GB of downloads. The scanner is a small read-only Deployment. The repository manual has the measured numbers per component.

Which of these give me one view across several clusters, self-hosted?

Dependency-Track and DefectDojo, if you model clusters as projects or products and feed each one; Harbor, for whatever all the clusters pull from it; a CronJob writing to one bucket, if you query the bucket. StackRadar Community Edition is one cluster per install; the fleet view is what the cloud edition is for, and it is how the open-source project is funded. Trivy Operator and Kubescape need an aggregation layer you build.

Does any of this replace scanning images in CI?

No. CI scanning answers "should this artefact ship"; everything on this page answers "what is running, and did a new advisory just land on it". Keep Trivy or Grype in the pipeline and add one of these for the cluster.

All posts