Posted in

Scanning Container Images in Helm Chart Deployments: Coverage Across the Stack

When teams audit their container security coverage, they typically check the images they build. What they overlook is the images they deploy but do not build — the third-party images that Helm charts pull from public registries as dependencies.

A standard Kubernetes application deployment using Helm might include: the application image (team-built), a database image (Bitnami PostgreSQL), a cache image (Redis), a proxy image (Nginx), and a monitoring agent (Prometheus node exporter). The team scans and maintains the application image. The other four run in the same cluster, with the same network access and pod permissions, and have never been evaluated for CVEs.

This is not a hypothetical gap. It is the standard state of most Helm-based deployments.


The Helm Image Inventory Problem

Helm charts reference container images in several places:

  • values.yaml image fields (image.repository, image.tag)
  • Sub-chart dependencies (Bitnami charts, community charts)
  • Init containers defined in chart templates
  • Sidecar injection configurations

A chart that looks like a single-image deployment at the application level can reference 8-12 images when all components are accounted for. Getting a complete inventory of which images a Helm chart will deploy requires rendering the full template output and parsing image references across all resource types.

# Render the full chart and extract image references

helm template myapp ./chart -f values.yaml | \

  grep -E “image:|initContainers|containers” | \

  grep -v “#”

This output is the starting point for scanning coverage. Every image in this list needs to be evaluated, not just the ones the team built.


The Third-Party Image Challenge

Third-party images from Bitnami, Docker Official Images, and community charts represent a specific challenge for container security: they are not under the team’s build control.

The team cannot modify the Dockerfile of a Bitnami PostgreSQL image. When that image has CVEs, the options are:

Wait for the upstream maintainer to release an updated image — and accept whatever CVE exposure exists in the meantime. For actively maintained images like Bitnami’s, updates are reasonably frequent. For less-maintained community charts, updates may be months apart.

Pin to a specific version and accept the static CVE footprint — knowing exactly what you have but not improving it. Many teams pin versions for stability reasons, creating accumulating CVE debt.

Apply hardening to the third-party image — the option that is underutilized but most effective. The third-party image is a container image like any other; it can be profiled against its expected usage, hardened to remove unused components, and pushed to your private registry under a controlled tag.


Hardening Third-Party Helm Dependencies

The approach:

  1. Identify the third-party images in your Helm chart inventory
  2. Profile each image against representative usage (the queries or operations it will perform in your deployment context)
  3. Apply container image security hardening based on the profiling output
  4. Push the hardened image to your private registry
  5. Override the Helm chart image reference to use your hardened version

# values.yaml override for a chart’s PostgreSQL dependency

postgresql:

  image:

    registry: registry.your-company.com

    repository: hardened/postgresql

    tag: 14.5-hardened-20241201

This approach gives the team control over the CVE state of all images in the Helm deployment, including the third-party ones. The hardened images in the private registry are known quantities — scanned, documented, and maintained by the team.


Curated Hardened Images for Common Dependencies

Some common Helm chart dependencies have hardened variants maintained by the security tooling vendor rather than the team. Instead of the team profiling and hardening a PostgreSQL image from scratch, they can use a pre-hardened version that has already been profiled against common PostgreSQL usage patterns.

These curated hardened images cover the most common Helm chart dependencies: PostgreSQL, MySQL, Redis, Nginx, Kafka, Elasticsearch, and others. They are maintained with regular CVE database updates and re-hardening as upstream images are updated.

For teams that deploy many Helm charts with common dependencies, curated hardened images dramatically reduce the effort required to achieve comprehensive scanning and hardening coverage across the full deployment stack.


Frequently Asked Questions

How do you scan all container images in a Helm chart deployment, including third-party dependencies?

Getting complete scanning coverage in Helm deployments requires rendering the full chart template and parsing image references across all resource types, including sub-chart dependencies, init containers, and sidecar configurations. Running helm template with all values files and extracting image references gives the complete inventory. Every image in that list — not just the application image the team built — must be scanned to achieve genuine coverage.

What are the options for managing CVEs in third-party Helm chart images you cannot modify?

Teams have three options for third-party images they do not build: wait for upstream maintainers to release updates, pin versions and accept the static CVE footprint, or apply hardening to the third-party image directly. Hardening the third-party image through runtime profiling and unused component removal, then pushing it to a private registry and overriding the Helm chart image reference, gives the team control over the CVE state of all images in the deployment stack.

Can pre-hardened images be used for common Helm chart dependencies like PostgreSQL and Redis?

Yes, curated pre-hardened images are available for many common Helm chart dependencies including PostgreSQL, MySQL, Redis, Nginx, Kafka, and Elasticsearch. These images have already been profiled against common usage patterns and hardened to remove unused components, with regular updates as upstream images change. For teams deploying multiple Helm charts with shared dependencies, using pre-hardened images avoids the effort of profiling and hardening each dependency from scratch.

How can container scanning be enforced at the Helm deployment level rather than just at build time?

Scanning at the deployment level requires pre-deployment image scanning before helm upgrade –install, admission control webhooks that block deployments of images not meeting CVE thresholds, and requiring all images to come from a controlled private registry. This ensures that even third-party chart dependencies pass through a scanning and hardening gate before they can run in the cluster, not just images the team builds directly.


Integrating Scanning into Helm Deployment Workflows

Scanning coverage in Helm environments requires automation at the deployment level, not just the build level:

Pre-deployment scanning: Before helm upgrade –install, scan all images that will be deployed by rendering the template and scanning each referenced image.

Admission control integration: Kubernetes admission webhooks can enforce that all images in a deployment have a valid scan record below a CVE threshold, blocking deployments of unscanned or unacceptable images regardless of whether they came from a team-built or third-party chart.

Registry pull enforcement: Requiring all images to come from a controlled private registry (rather than Docker Hub or Quay.io directly) ensures that only images that have passed through the scanning and hardening pipeline are available to deploy.

The goal is that when helm install runs, every image that gets pulled has already been evaluated and, where possible, hardened. The scanning gap that exists in most Helm deployments today — where application images are scanned and dependency images are not — is a solvable problem with the right tooling and process.