helm install --verify fails on a chart that installs fine without it. How do you diagnose it?
answer
- Only two checks can fail
- Take the cluster out of the picture first
- Missing sidecar, unknown key, or wrong bytes
- The .prov is readable — compare the digest yourself
- Re-packaging breaks provenance without changing files
basics
~20 sSplit 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.
solid answer
~50 s`--verify` adds exactly two checks, so the failure is always one of three things. **No provenance**: the repository serves `maildigest-2.14.3.tgz` but not the matching `.tgz.prov`, so there is nothing to check. **Key problem**: the keyring the runner used does not contain the signer's public key — a wrong `--keyring` path, an empty home directory on a fresh CI runner, or a modern GnuPG keybox rather than the legacy keyring format Helm reads. **Digest mismatch**: the tarball's bytes differ from what was signed, which in practice means something re-packaged the chart between signing and publication. Diagnose by taking the cluster out of the picture: `helm pull` the chart and its provenance to disk, run `helm verify` on the pair, read the `.prov` (it is clear text, so the digest and chart version are visible), and compare a locally computed SHA-256 against the `files:` entry.
code
bash · 10 lines# 1. pull chart + provenance, drop the cluster from the picture
helm pull internal/maildigest --version 2.14.3 --prov
ls maildigest-2.14.3.tgz* # is the .prov even there?
# 2. does the keyring hold the signer?
helm verify maildigest-2.14.3.tgz --keyring /etc/helm/trusted-signers.gpg
# 3. do the bytes match what was signed? (.prov is clear text)
sed -n '/^files:/,+2p' maildigest-2.14.3.tgz.prov
sha256sum maildigest-2.14.3.tgzgo deeper
Know the two things --verify needs before you can debug it: a .prov file next to the chart, and the signer's public key in the keyring you pass. Most failures at this level are one of those two being absent.
Practise reproducing the failure off-cluster with helm pull followed by helm verify, and be able to say which half of the check failed. Knowing that the .prov is readable text you can compare against a computed sha256 is the fastest tool you have.
Show a method rather than a guess: three causes, one command each, fixed at the layer that produced them. Name re-packaging by a mirror as the classic digest-mismatch source, and be explicit that removing the flag to unblock a pipeline is not a fix.
Argue about where this failure should surface at all. Verification at artifact ingress fails once, in a job you own, instead of intermittently across every cluster, and it lets you decide the response policy for a digest mismatch before an outage forces the decision.
`--verify` is a small surface, which is what makes this triage tractable: it can only fail for a handful of reasons, and each has a distinct signal. The scenario worth holding in mind is the ordinary one — an internal `maildigest` chart (the email-digest builder, version 2.14.3, a 240-line values file and a `values.schema.json` contract) that installs cleanly in a developer shell and fails in the pipeline the moment `--verify` is added. ### Step 0: separate the flag from everything else `helm install` without `--verify` proves nothing about provenance — it means the chart resolved and rendered. So do not start by comparing the two commands; start by removing the cluster entirely: ```bash helm pull internal/maildigest --version 2.14.3 --prov ls maildigest-2.14.3.tgz* helm verify maildigest-2.14.3.tgz --keyring /etc/helm/trusted-signers.gpg ``` If `helm verify` fails on the local pair, this has nothing to do with the cluster, the namespace, RBAC, or values. If the `.prov` never landed, you already have your answer. ### Cause 1: there is no provenance file For a chart resolved from a repository, `--verify` needs the server to host `<chart>-<version>.tgz.prov` beside the tarball. Publishers who ran `helm package` without `--sign` produce no such file; mirroring jobs frequently copy `*.tgz` and silently drop the sidecar; a repository that regenerates its index from tarballs it found on disk will happily list a chart whose provenance was never copied. The tell is that the file simply 404s. Fix it at the publisher: sign at package time and publish both artifacts as a unit, never one without the other. ### Cause 2: the key is not where Helm is looking `--keyring` defaults to `~/.gnupg/pubring.gpg`. A CI runner usually has no GnuPG home at all, so the default resolves to a nonexistent file and every signer is unknown. Even when a keyring exists, modern GnuPG keeps public keys in a keybox database rather than the legacy binary keyring Helm reads, so pointing at the wrong file gives you an empty trust set that looks identical to "signed by a stranger". The distinguishing evidence is that the failure is about the *signer or signature*, and it reproduces with a keyring you know is empty. The fix is to stop depending on ambient GnuPG state: build a keyring file containing exactly the public keys your organisation trusts, ship it to runners as a managed artifact, and pass `--keyring` explicitly everywhere. That also makes the trust set reviewable, which the developer's personal keyring never is. ### Cause 3: the digest does not match This is the interesting one, and the most common in an estate that mirrors charts. The `.prov` pins the SHA-256 of the exact tarball produced at signing. Anything that re-creates the archive — a mirror that unpacks and re-packs, a second `helm package` run publishing new bytes alongside the old `.prov`, a sync tool that "normalises" artifacts, a partially transferred file — changes those bytes and breaks the comparison while the signature over the document remains perfectly valid. You can confirm this by hand in seconds, because the `.prov` is clear-signed text: ```bash sed -n '/^files:/,+2p' maildigest-2.14.3.tgz.prov sha256sum maildigest-2.14.3.tgz ``` Two digests, one comparison. If they differ, no key or keyring change will ever help; the artifact you have is not the artifact that was signed. Fix the pipeline so the signed bytes are the published bytes — and if you need repeatable rebuilds, Helm 4's `helm package` honours `SOURCE_DATE_EPOCH` to keep tarballs reproducible. ### Cause 4, occasionally: mismatched pair A `.prov` from a neighbouring version can end up beside the wrong tarball after a hand-copy. The metadata block in the signed body names the chart and version, so reading the file tells you immediately that you are holding provenance for `2.14.2` next to a `2.14.3` tarball. ### What good triage looks like State the three buckets before touching anything, then collapse them with one command each: does the `.prov` exist, does the keyring contain the signer, does the digest match. Fix the cause at the layer that produced it — publisher, runner configuration, or mirror — rather than the layer that reported it. And say the thing an interviewer is listening for: dropping `--verify` to unblock the pipeline converts a genuine trust check into a comment in a runbook, so the flag is not the thing to remove while you investigate.
- How do you tell a keyring problem from a digest problem without guessing?Run helm verify on the local pair and read which half failed: an unknown-signer failure is about keys, a hash failure is about bytes. Then confirm the byte side by hand — the .prov is clear-signed text, so you can print its files: block and compare it to a locally computed sha256 of the tarball. Two independent digests either agree or they do not; there is nothing to infer.
- The CI runner has no GnuPG setup at all. What is the minimum it needs to verify a chart?A keyring file containing the public keys of the signers you trust, and --keyring pointing at it explicitly. No private key, no GnuPG agent, no personal keyring. Ship that file as a managed artifact rather than relying on ambient state on the runner, and remember Helm reads the legacy binary keyring format, so export from a modern GnuPG keybox before shipping it.
- The pipeline is blocked and the fix is upstream. Do you drop --verify to ship?Not silently. Dropping the flag turns a trust check into an assumption, and flags removed under pressure are rarely restored. Prefer installing a known-good verified version, or a documented, time-boxed exception with the artifact digest recorded and a ticket on the publisher. If the failure is a digest mismatch you should be more cautious, not less — that is the one cause consistent with tampering rather than misconfiguration.
saying these in an interview costs you the question
- Dropping --verify to unblock the build and moving on
- Assuming any failure means the chart was tampered with
- Blaming the cluster or RBAC for a provenance failure
- Not knowing the .prov must be served beside the .tgz
- Importing keys into a keyring Helm never reads
- Re-signing a mirrored chart to make the error go away