skip to content

Provenance & Signing

Helm's chart provenance is OpenPGP: helm package --sign writes a clear-signed .prov beside the .tgz, and install --verify checks it against a keyring. Probed because signing is opt-in and off by default.

part ofHelmoverview, primer and where to startread it →
on this pageshow

questions

4

Does helm install verify a chart's provenance by default, and how do you turn it on?

level: middleimportance: must knowfreq 52%

answer

  1. Trust is opt-in at both ends
  2. Nothing is checked unless asked
  3. A second file beside the tarball
  4. One flag on install, one keyring
  5. --verify plus --keyring, or it aborts

basics

~20 s

No. Helm checks a chart's OpenPGP signature only when you pass --verify, and only if the publisher signed the chart with helm package --sign so a .prov file exists, and the public key sits in the keyring you point --keyring at.

solid answer

~40 s

Helm's chart provenance is opt-in at both ends. A publisher runs `helm package --sign --key <name> --keyring <secret-keyring>`, which writes `<chart>-<version>.tgz.prov` beside the tarball: a clear-signed OpenPGP document holding the chart metadata and the tarball's SHA-256. A consumer gets no checking unless they ask for it — `helm install --verify` (also on `upgrade` and `pull`) fetches that `.prov`, validates the signature against a public keyring (`--keyring`, default `~/.gnupg/pubring.gpg`), then recomputes the tarball's digest and compares. Any failure — bad signature, unknown key, digest mismatch, or no `.prov` at all — aborts the command before templates are rendered or anything reaches the cluster. `helm verify <chart>.tgz` runs the same check on a local pair without installing. Most public charts ship no `.prov`, which is why the default is off.

code

bash · 14 lines
bash
# publisher: signing is opt-in
helm package --sign --key 'platform-releases' \
  --keyring ~/.gnupg/secring.gpg maildigest/
# -> maildigest-2.14.3.tgz  and  maildigest-2.14.3.tgz.prov

# consumer: no check at all
helm install digest maildigest-2.14.3.tgz

# consumer: signature + digest checked, or the command fails
helm install digest maildigest-2.14.3.tgz \
  --verify --keyring /etc/helm/trusted-signers.gpg

# same check, no cluster involved
helm verify maildigest-2.14.3.tgz --keyring /etc/helm/trusted-signers.gpg

go deeper

for a junior

Remember the one-line answer: Helm does not check chart signatures unless you pass --verify. Know that the check needs a .prov file next to the chart and a keyring holding the publisher's public key.

for a middle

Be ready to walk both halves of the mechanism: helm package --sign writing the .prov, and --verify performing a signature check plus a digest comparison. Say clearly that a failure aborts before anything is applied to the cluster.

for a senior

Show where the check belongs in a real pipeline: verify once at artifact ingress with helm verify rather than trusting every install site to remember a flag, and know the keyring-format and missing-.prov traps that make it fail on CI runners.

for a principal

Own the trust policy behind the flag. The keyring file is your entire trust model, so decide who curates it, how keys rotate, and whether you require upstream signatures or mirror-and-re-sign given that most published charts carry no provenance at all.

Helm's chart trust story is OpenPGP provenance, and the single most important fact about it is that it is **opt-in at both ends**: the publisher must choose to sign, and the installer must choose to check. Neither happens on its own. ### What signing produces `helm package --sign --key 'platform-releases' --keyring ~/.gnupg/secring.gpg maildigest/` packages the chart directory into `maildigest-2.14.3.tgz` and writes a second file next to it, `maildigest-2.14.3.tgz.prov`. That `.prov` is a clear-signed OpenPGP document — the body is readable text (the chart's metadata block, then a `files:` map naming the tarball and its SHA-256), wrapped in an armoured signature made with the publisher's private key. Signing is interactive by default because the private key normally has a passphrase; a CI job has to supply that passphrase non-interactively. Drop `--sign` and you get a tarball and nothing else. That is the state of nearly every chart you can download, which is the practical reason Helm cannot make verification the default: it would break the ecosystem on day one. ### What verifying does `--verify` exists on `helm install`, `helm upgrade` and `helm pull`. With it, Helm locates the chart, finds the `.prov` beside it (from a chart repository this means the server must also serve `<chart>-<version>.tgz.prov`), and then performs two distinct checks: 1. **Signature check** — is the clear-signed document signed by a key present in the public keyring? 2. **Digest check** — recompute the SHA-256 of the `.tgz` on disk and compare it to the value recorded in the `.prov`'s `files:` block. Both must pass. If either fails, or if there is no provenance file at all, the command fails *before* Helm renders templates and before it talks to the cluster. There is no advisory mode and no "installed but unverified" state: no release record is created and nothing is applied. ### The keyring `--keyring` names a **public** keyring file used for verification; it defaults to `~/.gnupg/pubring.gpg`. For signing you point the same flag at the secret keyring instead. Helm reads the older binary keyring format, while modern GnuPG stores public keys in a keybox database, so on a typical developer machine you export the signers you trust into a legacy keyring file and point `--keyring` at that. On a CI runner there is usually no GnuPG home at all, and the job materialises a keyring file from a stored artifact. Trust here is deliberately flat: "is this key in the file I named". Helm has no web of trust, no revocation lookup and no key-expiry policy of its own. Whoever curates that keyring file *is* your trust policy. ### helm verify `helm verify maildigest-2.14.3.tgz` runs the identical check against a local tarball and its `.prov`, printing the signing identity and the verified digest, without installing anything. That makes it the right tool for a promotion or mirroring job: verify once when the artifact enters your estate, rather than re-verifying on every install in every cluster. ### The plugin contrast Helm 4 made the opposite choice for plugins: `helm plugin install` verifies by default, and you opt out with `--verify=false`. Charts kept the opt-in default. The asymmetry is deliberate — plugin signing is a young surface Helm could make strict from the start, while charts have a decade of unsigned artifacts behind them. Knowing that Helm applies two different defaults to two of its own artifact types is a good discriminator; conflating them ("Helm verifies everything now") is a mistake. ### What verification buys you A passing `--verify` tells you two narrow things: the bytes have not changed since they were signed, and they were signed by a key you decided to trust. That is worth having — it is what stops a compromised mirror or a tampered tarball — but it is a statement about *bytes and signer*, not about what the chart's templates will do once rendered. ### Interview shape Say "no, nothing is checked unless you ask" first, then name the two halves (`--sign` at package time, `--verify` plus `--keyring` at install time), then say what a failure does (aborts before anything is applied). If you get a follow-up, the strongest additions are `helm verify` for out-of-band checking, the keyring-format trap on modern GnuPG, and the Helm 4 plugin default going the other way.

  • Helm 4 verifies plugins on install by default. Why are charts not treated the same way?
    Because the chart ecosystem predates the feature: almost no published chart carries a .prov, so defaulting helm install to --verify would fail nearly every install. Plugin signing is newer, so Helm 4 could make helm plugin install verify by default and offer --verify=false as the opt-out. The difference is ecosystem history, not a judgement that charts matter less.
  • What does helm verify give you that --verify on install does not?
    It checks a local .tgz and its .prov and stops there — no rendering, no cluster, no release. That fits a promotion or mirroring gate where you want to admit an artifact into your estate once, print and record the signing identity and digest, and then let downstream installs consume an artifact you already trust rather than re-checking in every cluster.
  • Your public keys live in a modern GnuPG keybox. What breaks, and what do you do?
    Helm reads the older binary keyring format, so pointing --keyring at a keybox database finds no keys and verification fails as if the signer were unknown. Export the signers you trust into a legacy keyring file and point --keyring at that file. On CI runners it is cleaner anyway: ship the keyring as a managed artifact rather than depending on whatever GnuPG home the runner happens to have.

Helm ships the lock and the key but never turns them for you: signing is the publisher taping a sealed slip to the box, and --verify is you choosing to read it. Skip either step and the box simply arrives.

saying these in an interview costs you the question

  • Assuming helm install checks signatures automatically
  • Thinking a successful download from a repository means verified
  • Believing helm package signs charts unless told not to
  • Treating the index.yaml digest as proof of publisher identity
  • Expecting --verify to work without the signer's public key
  • Saying a failed verification still installs with a warning

context

open as a page

helm install --verify fails on a chart that installs fine without it. How do you diagnose it?

level: seniorimportance: should knowfreq 33%

basics

~20 s

Split it into three causes: no .prov served beside the .tgz, a keyring that lacks the signer's public key or is in a format Helm cannot read, or a digest mismatch because the tarball was re-packaged after signing. Reproduce locally with helm pull then helm verify.

open as a page

How would you make Helm chart provenance verification actually enforced across an estate installing from an internal chart repository?

level: principalimportance: should knowfreq 27%

basics

~20 s

Verification is a client-side, opt-in flag, so enforcement means designing a single ingress path that verifies and re-signs charts, curating the keyring as a governed artifact, and accepting that a flag every install site must remember is not a control.

open as a page

What does helm package --sign write beside the .tgz, and what is inside that file?

level: middleimportance: nice to knowfreq 20%

basics

~10 s

It writes <chart>-<version>.tgz.prov: a clear-signed OpenPGP document whose readable body is the chart's metadata plus a files: block mapping the tarball name to its SHA-256, with the signature armoured underneath.

open as a page