A Helm chart is third-party code that creates ServiceAccounts, ClusterRoles and Secrets in your cluster with whatever permissions the person running Helm holds, and its release history keeps a copy of every value you passed in, passwords included. Helm is the default packaging tool for Kubernetes, so a single helm install from an unverified repository can add cluster-wide RBAC, admission webhooks and privileged DaemonSets in seconds. This guide covers chart provenance and signing, OCI registries and classic repositories, how Helm stores release data, secrets in values files, reviewing what a chart actually deploys, plugins and post-renderers, and the identity that Helm itself runs as. It reflects Helm 4, the current major version, with notes for teams still on Helm 3, and is written for platform engineers, DevOps teams and security reviewers.
Key takeaways
- Helm 4 is current and Helm 3 is ending. Helm v4.0.0 shipped in November 2025; Helm 3 had its final feature release on 9 September 2026 and security fixes end on 10 February 2027.
- Pin charts by digest and verify signatures. Install from OCI registries using
@sha256:digests, and verify.provfiles or Sigstore signatures before rendering. - Release records hold your secrets. Every revision is stored as a Kubernetes Secret containing the chart and the supplied values, so anyone with read access to Secrets in the release namespace can recover them.
- Render and review before you install. Use
helm templateand policy checks to see the ServiceAccounts, RBAC, hooks and CRDs a chart creates before they reach the cluster. - Helm runs as you. Since Tiller was removed in Helm 3, Helm uses the caller's kubeconfig, so the deployer identity, usually a CI service account, sets the blast radius.
Helm 3 and Helm 4: what changed for security
Helm 2 relied on Tiller, an in-cluster component; the Helm project's own FAQ describes its permissive default configuration as granting users permissions they were not intended to have. Helm 3 removed Tiller, renders charts client-side and evaluates permissions through the user's kubeconfig. Helm 4 (v4.0.0 released 12 November 2025, current line 4.3.x) keeps that model and changes several security-relevant behaviours.
| Area | Helm 3 | Helm 4 | Security effect |
|---|---|---|---|
| Support | Final feature release 9 September 2026; security fixes until 10 February 2027 | Actively developed | Plan migration before Helm 3 stops receiving patches |
| Plugins | Executables with the user's full rights | Optional WebAssembly runtime that runs in a sandbox with only approved access; plugin packaging, signing and verification (helm plugin install --verify, helm plugin verify) | Plugins can be verified and isolated |
| Post-renderers | --post-renderer takes an executable path | Post-renderers are plugins; the flag takes a plugin name | Post-render code goes through the plugin trust path |
| Chart integrity | Digest install supported for OCI | Install by digest; charts with non-matching digests are not installed; reproducible chart archives | Stronger pinning and rebuild verification |
| Apply method | Client-side three-way merge | Server-side apply by default for new releases; existing Helm 3 releases stay on client-side apply on upgrade | Field ownership conflicts surface rather than being overwritten |
| Registry login | Accepted full URLs | helm registry login accepts domain names only | Update CI scripts; prepares for per-scope credentials |
| Flags | --atomic, --force | --rollback-on-failure, --force-replace (old names deprecated) | Update pipelines to avoid warnings becoming failures later |
Distribution of the Helm binary matters too. In May 2026 the Helm Security Team warned that baltocdn.com, the former community APT mirror decommissioned in September 2025, had been re-registered by a third party on 19 May 2026, and advised treating any system that ran Helm binaries fetched from it after that date as compromised. Install Helm from the official release channels and pin checksums in build images.
Chart provenance, signing and pinning
Helm's native integrity mechanism is the provenance file. helm package --sign --key '<uid substring>' --keyring <path> creates mychart-1.2.3.tgz.prov next to the archive. The file contains the chart's Chart.yaml, a SHA256 digest of the package, and an OpenPGP signature over the whole body. helm verify, and the --verify flag on helm install, helm upgrade and helm pull, check it; if verification fails the install aborts before the chart is rendered. From Helm 4.3.0 verification reads GnuPG keybox files directly.
| Control | How | Protects against | Limits |
|---|---|---|---|
| Version pin | --version 1.2.3 or version: in Chart.yaml dependencies, locked in Chart.lock | Unexpected upgrades | A tag can be re-pushed with different content |
| Digest pin | helm install app oci://registry.example.com/charts/app@sha256:... | Tampered or replaced chart in the registry | Does not say who built it; you must trust the digest source |
| Provenance file (PGP) | helm package --sign; helm install --verify --keyring | Tampering and unknown publishers | Key distribution and rotation are manual; many public charts do not ship .prov files |
| Sigstore signing | helm-sigstore plugin, or signing the OCI artefact digest with container-signing tools | Tampering, with keyless identity tied to the publisher's build | Verification is outside core helm install; enforce it in CI or admission |
| Internal mirror | Pull approved charts into your own OCI registry after review | Upstream compromise between reviews; repository outages | Needs an update and re-review process |
Choosing: a small team consuming a few public charts gets most value from mirroring them into its own registry and installing by digest. Organisations that publish charts should sign every release (PGP provenance, Sigstore or both) and publish the verification identity. Regulated or multi-cluster estates should verify signatures in the pipeline and again at admission. Verification only means something if the reader knows which key or identity to expect. See the Code Signing Security Guide and the Software Supply Chain Security Guide.
Repositories: OCI registries versus classic chart repositories
- OCI registries: charts are pushed with
helm push mychart-0.1.0.tgz oci://registry.example.com/helm-chartsand consumed withoci://references inhelm pull,install,upgrade,showandtemplate. A.provfile next to the archive is uploaded automatically as an extra layer. Registry access control, immutability settings, audit logs and vulnerability scanning come from the registry platform you already run for images. - Classic HTTP repositories: an
index.yamlplus archives on a web server, added withhelm repo add. Integrity depends on TLS and on whoever can write to the bucket or server, and the index can be changed to point at different archives. - Dangerous flags:
--insecure-skip-tls-verifyand--plain-httpremove transport protection for chart downloads;--pass-credentialssends repository credentials to every domain the download is redirected to. Use--ca-filefor private CAs instead, and block the others in pipeline linting. - Registry credentials are NHIs:
helm registry loginstores credentials on the machine running Helm, usually a CI runner. Use short-lived registry tokens from workload identity federation, give pull-only rights to deployers and push rights only to the release pipeline. Leaked registry credentials are a recurring problem: in the exposed Kubernetes Secrets research, Aqua found 203 valid registry credentials in Kubernetes Secret manifests on public GitHub, mostly with push rights.
Release storage and secrets in values
Helm records every release revision in the cluster. By default the storage driver is secret: each revision becomes a Secret named sh.helm.release.v1.<release>.v<revision>, labelled owner=helm, in the release namespace. The payload is the release (chart, templates, manifest and supplied values) gzip-compressed and base64 encoded, which is encoding, not encryption. The Helm documentation states plainly that release information can contain passwords, private keys and other credentials.
HELM_DRIVER | Where data lives | Who can read it | Notes |
|---|---|---|---|
secret (default) | Secrets in the release namespace | Anyone with get or list on Secrets there, including holders of the built-in edit role | Covered by etcd encryption at rest when configured |
configmap | ConfigMaps | Anyone with ConfigMap read, including the built-in view role | Helm warns this could expose sensitive data; avoid |
sql (beta) | PostgreSQL via HELM_DRIVER_SQL_CONNECTION_STRING | Database roles; isolation uses PostgreSQL row-level security, not Kubernetes RBAC | For releases over 1MB; the connection string itself is a secret |
- Keep secrets out of values: reference existing Secrets by name (
existingSecretpatterns) created by an external secrets operator, CSI secrets driver or sealed secrets workflow, so the release record never contains the plaintext. Values passed with--setalso appear in shell history and CI logs. - Limit history:
helm upgrade --history-maxdefaults to 10 revisions; every retained revision is another copy of old credentials. Rotate any secret that ever passed through values, then prune history. - Encrypt etcd: configure an
EncryptionConfigurationwith thekmsv2 provider (v1 is deprecated since Kubernetes 1.28) so release Secrets are encrypted at rest. - Restrict reads:
helm get valuesandhelm get allwork for anyone who can read the release Secrets. Keep Secret read in release namespaces to the deployer and break-glass roles. See the Secrets Management Guide.
Reviewing what a chart deploys
A chart's risk is in the manifests it renders, including those of its subcharts. Render first with helm template (or helm install --dry-run=server if templates use lookup), then review and scan the output.
| Look for | Why it matters | What to do |
|---|---|---|
| ClusterRoles and ClusterRoleBindings | Charts often ship "*" rules, Secret access across namespaces or bindings to cluster-admin | Set rbac.create=false and supply reviewed RBAC, or patch rules; see the Kubernetes RBAC Guide |
| ServiceAccounts | Best-practice charts expose serviceAccount.create and serviceAccount.name; if both are unset the namespace default account is used | Always set a dedicated name and automountServiceAccountToken: false when the app does not call the API |
Hooks (helm.sh/hook annotations) | Hook resources such as Jobs run at pre-install or post-upgrade and are not tracked or deleted with the release | Review hook Jobs like any workload; require helm.sh/hook-delete-policy so they do not linger |
helm.sh/resource-policy: keep | Resources survive helm uninstall | Track kept Secrets, PVCs and RBAC so they are cleaned up deliberately |
CRDs in crds/ | Installed as plain YAML, cannot be templated, cluster-scoped | Require cluster-admin approval; check aggregation labels that extend admin, edit or view |
lookup in templates | Reads live cluster objects, including Secrets, with the caller's credentials during render | Grep templates for lookup; ensure rendered output is not logged |
Webhooks, privileged pods, hostPath, host networking | Cluster-wide interception or node access | Enforce Pod Security Standards and policy at admission; see the Kubernetes Admission Control Guide |
| Subchart sources | Dependencies in Chart.yaml may pull from other repositories | Commit Chart.lock, mirror dependencies, rebuild with helm dependency build |
Add values.schema.json to internal charts so invalid or unexpected values fail at install, and lint rendered output in CI with the same policy engine that guards admission. Container images referenced by the chart need their own scanning and signing; see the Container Image Security Guide.
Plugins, post-renderers and the Helm identity
- Plugins: in Helm 4 legacy plugins still run as arbitrary executables with the user's rights, while WebAssembly plugins run in a sandbox. Verify provenance on install (
helm plugin install --verify), audit installed plugins withhelm plugin listandhelm plugin verify, and bake an approved set into CI images. - Post-renderers: they receive every rendered manifest, often containing secret data, and can change it. Helm's documentation warns against non-trusted or non-verified renderers. Everyone changing a release must use the same post-renderer, or later upgrades will silently revert changes.
- The deployer identity: Helm does exactly what its kubeconfig allows. A CI service account with
cluster-adminlets any chart, hook or compromised pipeline step do anything. Give each pipeline a service account per target namespace with a Role covering the resource kinds its charts create, plus a separately approved path for cluster-scoped resources such as CRDs and ClusterRoles. Prefer federated short-lived credentials over kubeconfig files stored as CI secrets. See the CI/CD Pipeline Identity Security Guide. - GitOps controllers: where Argo CD or Flux render charts, the controller's service account becomes the deployer identity and usually holds broad rights across namespaces; apply the same scoping and verification there. See the GitOps Security Guide.
Implementation roadmap
- Inventory: list releases across clusters (
helm list -A, orkubectl get secret -A -l owner=helm), the chart source and version of each, the Helm client versions in use, and which identities run Helm. - Upgrade the client: move CI images and workstations to Helm 4, test charts and post-renderer plugins in a non-production cluster, and update renamed flags and registry login commands. Remove any
baltocdn.comAPT sources. - Find secrets in release history: decode release Secrets in a controlled environment, identify credentials passed through values, rotate them, migrate to
existingSecretreferences and reduce--history-max. - Mirror and pin: copy approved charts into an internal OCI registry, record digests, and switch installs to digest references. Turn on registry immutability for chart repositories.
- Add verification in audit mode: run
helm verifyor Sigstore verification in the pipeline and log failures for a release cycle before making them blocking. - Gate rendered manifests: render every change with
helm template, run policy checks for RBAC, privileged pods and webhooks, and require approval for cluster-scoped objects. - Scope deployer identities: replace shared cluster-admin deployers with per-namespace service accounts, piloting one team at a time.
- Rollback:
helm rollback <release> <revision>restores a previous revision, and verification gates can be switched back to warn-only by pipeline configuration if a signing issue blocks an urgent fix. Keep the previous Helm 3 build image available until the Helm 4 migration is signed off.
Detection and measurement
- Release Secret reads: alert in API server audit logs on
getorlistof Secrets with names startingsh.helm.release.v1.by anyone other than deployers. - Unexpected cluster-scoped changes: creation of ClusterRoleBindings, webhook configurations or CRDs by deployer service accounts outside approved changes (ATT&CK T1098.006).
- Drift: releases whose chart digest does not match the approved list, or images not from the internal registry (T1525 for implanted images).
- Pipeline signals: verification failures, use of
--insecure-skip-tls-verifyor--plain-http, and new plugins in runner images.
| Metric | Target |
|---|---|
| Releases installed from a digest-pinned internal registry | 100% in production |
| Releases whose chart signature was verified in the pipeline | Rising to 100% for internally published charts |
| Release revisions containing plaintext credentials in values | Zero |
Deployer identities holding cluster-admin | Zero, except a documented platform bootstrap path |
| Helm clients on Helm 3 | Zero before 10 February 2027 |
| Third-party charts re-reviewed after upstream version change | 100% before promotion |
Framework mapping
| Framework | Reference | Helm control |
|---|---|---|
| NIST SP 800-53 Rev. 5 | CM-14 Signed Components, SR-4 Provenance, SR-11 Component Authenticity, SI-7 Software, Firmware, and Information Integrity | Provenance files, Sigstore signatures, digest pinning |
| NIST SP 800-53 Rev. 5 | CM-3 Configuration Change Control, CM-5 Access Restrictions for Change, AC-6 Least Privilege, SC-28 Protection of Information at Rest | Rendered manifest review, scoped deployer identities, encrypted release Secrets |
| NIST CSF 2.0 | PR.PS-01, PR.DS-01, PR.AA-05 | Configuration management of charts, release data at rest, deployer least privilege |
| ISO/IEC 27001:2022 Annex A | 8.9 Configuration management, 8.19 Installation of software on operational systems, 8.32 Change management | Approved chart catalogue, pipeline gates |
| MITRE ATT&CK | T1195.002 Compromise Software Supply Chain, T1525 Implant Internal Image, T1552.001 Credentials In Files, T1552.007 Container API, T1098.006 Additional Container Cluster Roles | Detection and threat modelling for chart supply chain and release data |
Common failure patterns
- Database and API passwords in values files: they end up in Git, CI logs and every release revision Secret. The exposed Kubernetes Secrets research shows how often credentials in committed Kubernetes manifests are still valid years later.
- Installing straight from public repositories by tag: no review, no digest and no signature check, so whatever the repository serves on the day is deployed.
- A cluster-admin CI deployer: a single compromised pipeline step or malicious chart hook gains full control of the cluster.
- Accepting chart RBAC defaults: monitoring and operator charts commonly create ClusterRoles with Secret read across namespaces that nobody reviewed.
- Switching to the ConfigMap driver for convenience: release data, including values, becomes readable by the built-in
viewrole. - Stale installation sources: build images and scripts that still fetch Helm from retired mirrors, as the
baltocdn.comnotice showed.
Practitioner checklist
- Move every CI image and workstation to Helm 4 and remove Helm 3 before security fixes end on 10 February 2027.
- Mirror approved charts into an internal OCI registry and install by
@sha256:digest. - Sign internally published charts and verify signatures in the pipeline with a known key or identity.
- Render with
helm templateand gate RBAC, hooks, CRDs, webhooks and privileged pods through policy checks. - Keep credentials out of values; use
existingSecretreferences and rotate anything that ever passed through values. - Keep the default
secretstorage driver, encrypt etcd with KMS v2 and restrict Secret read in release namespaces. - Give each pipeline a namespace-scoped deployer service account with short-lived credentials.
- Verify plugins on install, keep an approved plugin list, and treat post-renderers as privileged code.
- Block
--insecure-skip-tls-verify,--plain-httpand--pass-credentialsin pipeline linting.
Standards and references
- Helm: Provenance and Integrity
- Helm: Use OCI-based registries
- Helm: Advanced Helm Techniques (post rendering and storage backends)
- Helm: Helm 4 Overview
- Helm: Helm 3 End of Life
- Helm: Security Notice: Former Helm APT Mirror Domain baltocdn.com Statement
- Kubernetes: Using RBAC Authorization
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: Kubernetes Security Guide · Kubernetes NHI Security Guide · Software Supply Chain Security Guide · Secrets Management Guide · NHI Authentication Guide