skip to content

Why does helm plugin install verify signatures by default in Helm 4, and how do you opt out?

level: middleimportance: must knowfreq 50%

answer

  1. One artefact is data, the other is code
  2. Which one runs with your credentials
  3. Helm 4 flipped one default, not both
  4. The opt-out is the same flag, negated
  5. helm plugin package --sign on the publisher side

basics

~20 s

A plugin is code Helm executes locally with your kubeconfig and credentials, so Helm 4 defaults helm plugin install --verify to true and refuses a plugin it cannot verify. The opt-out is the explicit --verify=false.

solid answer

~40 s

Helm 4 flipped the default because the risk profile of a plugin is unlike that of a chart. A chart is data that Helm renders into manifests; a plugin is code Helm executes locally, inheriting your shell environment, kubeconfig and any cloud credentials in it. So `helm plugin install` sets `--verify` to true by default: if the plugin has no signature Helm trusts, the install fails rather than proceeding. The escape hatch is the explicit `--verify=false`; there is no separate allow-insecure flag. On the publishing side, `helm plugin package --sign` produces a signed plugin package, and `helm plugin verify` checks one on its own. Note the deliberate asymmetry with chart provenance, which remains opt-in — `helm package --sign` and `helm install --verify` are both things you choose. Only plugin signing is on by default.

code

bash · 4 lines
bash
helm plugin package --sign --key ops-signing ./values-lint
helm plugin verify ./values-lint-0.4.2.tgz
helm plugin install ./values-lint-0.4.2.tgz
helm plugin install https://example.com/git/values-lint --verify=false

go deeper

for a junior

Know that in Helm 4 installing a plugin verifies it by default and that the way to install an unsigned one is the explicit --verify=false. Do not invent a different flag name for the opt-out.

for a middle

Explain the reasoning: a plugin is executed code, a chart is rendered data, so the defaults differ. Be able to name helm plugin package --sign and helm plugin verify and say what a signature does and does not prove.

for a senior

Show a plan for an estate whose existing plugins are unsigned: mirror and sign at ingest, keep any --verify=false confined to one reviewed image build, pin versions, and reduce what credentials sit in the environment where Helm runs.

for a principal

Own the trust policy: whose key signs internal plugins, how public keys reach every laptop and runner, which plugins are sanctioned at all, and when the right answer is HELM_NO_PLUGINS in automation images rather than a signing programme.

### The threat that motivates the default Helm distinguishes two very different things it fetches from the internet. A chart is data: Helm renders it with Go text/template and sends the resulting manifests to an API server. A plugin is code: Helm executes it, as a child process or a WebAssembly module, on the machine running the CLI. That machine is usually either an engineer's laptop with a full kubeconfig and cloud credentials in the shell, or a CI runner with a deploy identity for every environment. A malicious plugin does not need to exploit anything — it simply runs, with what you already have. That asymmetry is why Helm 4 made `--verify` on `helm plugin install` default to **true**, while chart provenance stayed opt-in. If you can only remember one contrast from this area, make it that one: **plugin signing is verified by default; chart signing is not.** ### What the default actually does With verification on, `helm plugin install <source>` will refuse to install a plugin whose signature is missing or cannot be validated against the keyring Helm consults. The install fails; nothing lands in the plugin directory. This is the change that breaks existing automation on upgrade: a Dockerfile line or bootstrap script that installed an unsigned community plugin under Helm 3 now fails under Helm 4, and the fix is a deliberate decision, not a retry. The opt-out is the explicit negation of the same flag: ```bash helm plugin install https://example.com/git/values-lint --verify=false ``` There is no separate insecure-plugins flag to reach for — if you find yourself hunting for one, you are remembering a flag that does not exist. `--verify=false` is the whole opt-out surface, and its explicitness is the point: someone had to type it, and it shows up in a diff and in a shell history. ### The publishing side A publisher packages a plugin with `helm plugin package`, and adds `--sign` to sign the result. Signing uses OpenPGP, the same signing machinery Helm uses for chart provenance, so the practical prerequisites are the familiar ones: a secret key to sign with, the key name to select it, and a way to supply the passphrase non-interactively in CI rather than having a job block on a prompt. Consumers need the corresponding public key available in the keyring Helm checks, which is exactly the distribution problem signing always has — the signature is worthless if the verifying side accepts any key it happens to be handed. `helm plugin verify` checks a packaged plugin on its own, separately from installing it. That is useful in a pipeline that mirrors third-party plugins into an internal location: verify once at ingest, then serve the vetted copy internally. ### Operating this at an organisation The interesting judgement is what to do about the plugins your teams already depend on that nobody signs. Three honest paths: 1. **Sign them yourself at ingest.** Fetch the upstream plugin, review it, package and sign it with an internal key, and publish the signed artefact to an internal location. Engineers and runners then install with verification on, against your key. This is the only path that keeps verification meaningful and still lets you use community plugins. 2. **Allow `--verify=false` narrowly, in a place a human reviews.** Confined to a base image build where the source and version are pinned, an unsigned install is a bounded, reviewable decision. Sprinkled through deploy jobs, it is a default that has quietly been turned off everywhere. 3. **Run without plugins.** `HELM_NO_PLUGINS=1` makes Helm load no plugins at all. For an automation image that should only ever perform stock installs and upgrades, that is the strongest and simplest posture. ### What verification does not give you Be precise about the guarantee. A valid signature says the artefact is unmodified since the holder of that key signed it. It says nothing about whether the code is safe, whether the publisher's key was stolen, or whether the version you pinned yesterday is the version being installed today unless you also pin it. Verification defends against tampering in transit and against a substituted artefact; it does not review code, and it is not a substitute for pinning versions and limiting what credentials a runner holds when Helm runs there. Finally, keep the vocabulary straight in an interview. `helm plugin verify` and `--verify` on `helm plugin install` concern plugin packages. `helm verify` and `--verify` on chart commands concern chart provenance and the clear-signed file that sits beside a chart archive. Same word, two artefacts, and opposite defaults — that pairing is precisely what an interviewer is testing when they ask this.

  • Chart provenance is still opt-in while plugin verification is on by default. Why the difference?
    Because the artefacts do different things. A chart is rendered into manifests that the API server then admits, validates and policy-checks; a plugin is executed directly by the CLI with whatever credentials the caller holds. The blast radius of a tampered plugin is the operator's machine and every cluster their kubeconfig reaches, and it lands before any cluster-side control can see it. Helm chose a secure default where the failure is local code execution and left the chart path opt-in.
  • Your CI image installs three community plugins, none of them signed, and the Helm 4 upgrade broke the build. What do you do?
    Do not scatter --verify=false through deploy jobs. Prefer mirroring: fetch each plugin at a pinned version, review it, package and sign it with an internal key, publish it internally, and install with verification on against that key. If that is too much for a low-risk plugin, allow --verify=false in exactly one reviewed place — the image build, with the source and version pinned — so the exception is visible in a diff rather than being the ambient default.
  • A plugin install succeeded with a valid signature. What have you actually proved?
    Only that the artefact has not changed since the holder of that key signed it, and that you trust that key. You have not proved the code is safe, that the publisher's key was not stolen, or that this is the version you meant to install. Signature verification pairs with version pinning and with limiting the credentials available where Helm runs; on its own it addresses tampering and substitution, nothing more.

saying these in an interview costs you the question

  • Names a nonexistent allow-insecure-plugins flag
  • Says chart signing is also on by default
  • Thinks --verify only checks a checksum of the download
  • Claims a valid signature means the code is safe
  • Believes Helm 3 verified plugins the same way
  • Puts --verify=false in every deploy job as the fix

context