Securing Helm Charts with Signed Provenance Verification
In the modern Kubernetes ecosystem, the Helm chart is the fundamental unit of deployment. It defines the desired state of your applications, encompassing everything from container images and environment variables to complex ConfigMaps and RBAC roles. However, as organizations increasingly adopt GitOps and automated CI/CD pipelines, the Helm chart has become a high-value target for supply chain attacks.
If an attacker successfully compromises a Helm registry or intercepts a chart during transit, they can inject malicious sidecars, escalate privileges via modified ServiceAccounts, or exfiltrate secrets by altering ConfigMaps. Traditional security measures, such as TLS for registry communication, protect the "pipe" but do nothing to protect the "payload." To achieve true zero-trust deployment, we must move beyond simple transport security and implement signed provenance verification.
The Core Problem: Integrity vs. Provenance
When discussing security in the software supply chain, it is vital to distinguish between two often-conflated concepts: integrity and provenance.
- Integrity ensures that a file has not been altered since it was created. This is typically achieved through checksums (e.g., SHA-256 hashes). While a checksum can tell you if a chart was tampered with after the hash was generated, it cannot tell you who generated that hash.
- Provenance provides the "chain of custody." It answers the question: "Who built this artifact, and through what process was it produced?"
A cryptographically signed Helm chart provides both. By using a digital signature, we verify that the chart's digest matches the signed manifest (integrity) and that the signature was produced by a trusted identity (provenance).
The Shift to OCI: The Foundation of Modern Signing
Historically, Helm charts were distributed via indexed repositories using the `index.yaml` format. This format was difficult to sign effectively because the `index.yaml` itself is a moving target.
The industry has pivoted toward OCI (Open Container Initiative) registries. Helm can now package and push charts directly to container registries (like ECR, ACR, or GHCR) as OCI artifacts. This is a paradigm shift for security because it allows us to leverage the mature ecosystem of container signing tools-most notably Sigstore/Cosign-to treat Helm charts exactly like container images.
Implementing Provenance with Cosign
To implement signed provenance, we utilize the Sigstore ecosystem. The goal is to create a workflow where a chart is signed during the CI process, and the deployment controller verifies that signature before any manifest is applied to the cluster.
1. The Signing Workflow (CI Pipeline)
In your CI pipeline (e.g., GitHub Actions, GitLab CI), after the Helm chart is packaged and pushed to an OCI registry, you must generate a signature.
```bash
1. Package the chart
helm package ./my-app-chart
2. Push the chart to an OCI registry
helm push my-app-chart-0.1.0.tgz oci://ghcr.io/my-org/charts
3. Sign the chart using Cosign
Using keyless signing with Sigstore's Fulcio and Rekor
cosign sign --yes ghcr.io/my-org/charts/my-app-chart:0.1.0
```
In the "keyless" flow demonstrated above, Coscosign uses OIDC (OpenID Connect) to obtain a short-lived certificate from the Fulcio CA, tying the signature to the identity of the CI runner. This eliminates the massive operational burden of managing long-lived private keys.
2. The Verification Workflow (CD/Admission Control)
Signing is useless if the cluster blindly accepts unsigned charts. Verification must happen at the "gate"-the point of entry into the Kubernetes API.
The most robust way to implement this is via a Kubernetes Admission Controller like Kyverno or Policy Agent (OPA/Gatekeeper). These tools can intercept `helm install` or `helm upgrade` operations (or more accurately, the resulting manifest applications) and verify the signature against a trusted root of trust.
An example Kyverno policy for verifying an OCI Helm chart signature might look like this:
```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-helm-chart-provenance
spec:
validationFailureAction: Enforce
rules:
- name: check-signature
match:
any:
- resources:
kinds:
- ConfigMap # Example: verifying the chart's output
- Deployment
verifyImages:
- imageReferences:
- "ghcr.io/my-org/charts/my-app-chart:*"
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
... (Your Trusted Public Key) ...
-----END PUBLICKEY-----
```
*Note: While Kyverno's `verifyImages` is primarily for container images, the logic extends to verifying the OCI artifacts (the charts themselves) via custom webhooks or specialized
Conclusion
As shown across "The Core Problem: Integrity vs. Provenance", "The Shift to OCI: The Foundation of Modern Signing", "Implementing Provenance with Cosign", a secure implementation for securing helm charts with signed provenance verification depends on execution discipline as much as design.
The practical hardening path is to enforce deterministic identity policy evaluation with deny-by-default semantics, admission-policy enforcement plus workload isolation and network policy controls, and certificate lifecycle governance with strict chain/revocation checks. This combination reduces both exploitability and attacker dwell time by forcing failures across multiple independent control layers.
Operational confidence should be measured, not assumed: track false-allow rate and time-to-revoke privileged access and mean time to detect and remediate configuration drift, then use those results to tune preventive policy, detection fidelity, and response runbooks on a fixed review cadence.