A Helm chart is not just a wrapper around a container image — it renders RBAC bindings, network policies, volume mounts, resource limits, and default passwords, and every one of those fields can be insecure even when the image it references has a clean vulnerability report. Artifact Hub, the CNCF's public chart registry, now lists more than 8,000 charts, and most production Kubernetes clusters run at least a handful of them from Bitnami, the successors to the deprecated stable repo, or internal chart museums. Helm chart security scanning is the practice of checking the rendered manifest a chart produces — not just the image tag it points to — against baselines like the CIS Kubernetes Benchmark and the Kubernetes Pod Security Standards before helm install or helm upgrade ever executes. This post covers what that scan actually checks, the specific misconfigurations that show up most often, the incident that forced Helm to redesign its own architecture, and how to wire chart scanning into a CI/CD pipeline without slowing down releases.
What is Helm chart security scanning?
Helm chart security scanning is the automated inspection of a chart's templates, values.yaml defaults, and image references for misconfigurations and known vulnerabilities before deployment. It is a different job than helm lint, which only checks that a chart is well-formed Go templating and valid YAML — lint will happily pass a chart that runs as root, mounts the host's Docker socket, or disables readOnlyRootFilesystem. Real scanning renders the chart (helm template) with representative values, then evaluates the output against policy sets covering privilege escalation, network exposure, secret handling, and admission-control compatibility. A chart that sets securityContext.privileged: true or hostNetwork: true in its default values will pass helm lint cleanly and fail a security scan immediately, which is exactly the distinction teams need to catch before a chart reaches a cluster instead of after.
Why aren't container image scans enough to secure a chart?
Container image scans aren't enough because a chart can wire a perfectly clean image into an insecure runtime configuration that no image scanner ever sees. Image scanners like Trivy or Grype check the filesystem layers of an image for known CVEs in installed packages; they have no visibility into the RBAC ClusterRoleBinding, network policy, or environment variables a Helm chart generates around that image at deploy time. A well-documented example: several popular database charts on Artifact Hub historically shipped with authentication disabled unless an operator explicitly set a password value, meaning the "insecure by default" behavior lived entirely in values.yaml and the deployment template — nowhere near the image layer a scanner inspects. The container passed every CVE scan. The cluster was still exposed.
What security issues show up most often in Helm charts?
The issues that show up most often are privilege escalation defaults, missing network isolation, and mutable image tags. Concretely: charts that set runAsNonRoot: false or omit a securityContext entirely, so pods inherit root by default; charts with no NetworkPolicy template at all, leaving every pod reachable from anything else in the namespace; charts that pin dependency images to :latest or a floating tag rather than a digest, so the same chart version can deploy a different — and differently vulnerable — image on two different days; and charts that pass secrets as plain values.yaml strings instead of referencing a Kubernetes Secret or external secret manager, which means credentials end up committed to Git in whatever repo stores the Helm values overrides. Artifact Hub's own security report feature, which scans listed charts' referenced images with Trivy, regularly surfaces charts still pointing at images with unpatched critical CVEs months after a fix has shipped upstream — the chart's version number moves on, but nothing forces the image reference to move with it.
How did Helm's original architecture cause its worst security incident?
Helm's worst security incident came from Tiller, the server-side component in Helm 2 that ran inside the cluster with cluster-admin privileges by default. In many deployments, Tiller's gRPC endpoint on port 44134 had no authentication in front of it, so anyone with network access to that pod — including, in a number of documented cases, anyone on the open internet who found an exposed cluster via Shodan-style scanning in 2018 and 2019 — could deploy, upgrade, or delete arbitrary workloads with cluster-admin rights. Security researchers used mass internet scans during that period to catalog publicly reachable Tiller instances, turning a convenience feature into one of the most cited examples of "insecure by default" in the Kubernetes ecosystem. Helm's maintainers responded by removing Tiller entirely: Helm 3, released on November 13, 2019, moved to a client-side-only model where helm talks directly to the Kubernetes API using the user's own RBAC permissions, eliminating the always-on cluster-admin daemon as an attack surface.
What tools and standards do teams use to scan Helm charts today?
Teams typically combine four layers: chart linting, static policy checks, image vulnerability scanning, and runtime admission control. Linting (helm lint, chart-testing) catches structural errors. Static policy tools — Checkov, kube-score, kubeaudit, and Open Policy Agent's Conftest — render the chart and check the output against baselines like the CIS Kubernetes Benchmark and the Pod Security Standards that replaced PodSecurityPolicy after its removal in Kubernetes 1.25 (released August 2022). Image scanning (Trivy, Grype) covers the CVEs in whatever images the chart's values.yaml resolves to. Runtime admission controllers — Kyverno or OPA Gatekeeper — enforce the same policy set at the API server as a backstop for anything that bypasses the pipeline, such as a manual helm upgrade run from someone's laptop. No single tool in that list covers all four layers, which is why most real-world chart security failures trace back to a gap between them rather than a gap in any one tool.
How do you add Helm chart scanning to a CI/CD pipeline?
You add Helm chart scanning to CI/CD by rendering the chart and running policy checks against the output before helm install or helm upgrade ever executes against a real cluster. A minimal pipeline: run helm template ./chart -f values-prod.yaml > rendered.yaml to produce the actual manifest a deploy would apply; run that output through conftest test rendered.yaml -p policies/ or checkov -f rendered.yaml to catch policy violations; run trivy config rendered.yaml to catch image and configuration CVEs in the same pass; and gate the pull request merge on a non-zero exit code from any of those steps rather than letting a human eyeball the diff. Mirror the same policy set in a Kyverno or Gatekeeper admission policy in the target cluster so a chart deployed outside the pipeline — via helm from a laptop, or a break-glass emergency change — is still blocked or flagged rather than silently accepted. Catching a privileged-container default at pull-request time costs one CI run; catching it after it's running in production costs an incident.
How Safeguard Helps
Safeguard treats a Helm chart the same way it treats any other artifact in the software supply chain: rendered, inventoried, and continuously checked, not linted once and forgotten. When a chart is scanned, Safeguard renders every template path — including conditional blocks driven by values overrides — generates an SBOM covering both the chart's dependencies and every container image it references, and runs reachability analysis to determine whether a flagged CVE in a bundled image is actually exercised by the workload the chart deploys, cutting through noise from vulnerabilities sitting in unused code paths. Griffin, Safeguard's AI security agent, correlates those findings with the chart's RBAC bindings and network policy templates to catch combinations — like a privileged pod paired with a wildcard ClusterRoleBinding — that scanners checking one file at a time miss entirely. Safeguard ingests SBOMs and chart metadata from existing pipelines rather than requiring a rip-and-replace, and for fixable issues it opens an auto-fix pull request with the corrected values.yaml default or template change instead of just filing a ticket. That turns a scan finding into a merged fix, not another line in a backlog.