Safeguard
Cloud Security•

External Secrets CVE-2026-26287: Webhook Generator Skips Its Label Check

An init-order bug let External Secrets Operator's webhook generator read Secrets not labeled for it and send them to any URL. Fixed in 1.3.2, disclosed 6 October.

Safeguard Security Team
5 min read

On 6 October 2026 the External Secrets Operator (ESO) project published CVE-2026-26287 (GHSA-q7hv-xx6h-q2x8, CVSS 3.1 score 7.1). A bug in how the Webhook generator initialized itself cleared the flag that enforces ESO's label check. The result: a generator could read a Secret that was never labeled for webhook use and send its contents to whatever URL the generator's author chose.

The fix shipped in ESO v1.3.2 back on 3 February 2026. The advisory came eight months later, which means many teams that upgraded past 1.3.2 were protected without knowing it, and teams still pinned to older releases had no signal to move.

What's affected

  • Package: github.com/external-secrets/external-secrets
  • Affected: 0.10.0 up to, but not including, 1.3.2
  • Fixed: 1.3.2 and later

ESO's webhook integration has a guard. Any Secret the webhook provider or webhook generator reads must carry the label external-secrets.io/type: webhook. Without it, the lookup is supposed to fail with:

secret does not contain needed label 'external-secrets.io/type: webhook'. Update secret label to use it with webhook

In affected versions, the generator's setup code set EnforceLabels and then cleared it again, so the check never ran. The advisory's impact statement: "A user with the permission to create webhook generator can set the webhook generator to a victim' secret (which was not previously labelled for webhook's use), and exfiltrate it to a malicious URL."

That matters because ESO's controller reads Secrets with its own service account. In many clusters, application teams may create ESO resources but are deliberately not allowed to get Secrets. The label is what keeps the controller from becoming a way around that rule. The fix is PR #5901, "fix: webhook initialization order", credited to reporters 1seal and evrardj-roche.

How to check if you're exposed

Find the ESO controller version in each cluster:

kubectl get deploy -A -l app.kubernetes.io/name=external-secrets \
  -o jsonpath='{range .items[*]}{.metadata.namespace}{"  "}{.spec.template.spec.containers[0].image}{"\n"}{end}'

Anything from v0.10.0 to v1.3.1 is affected. If the image is from a mirror or a vendor build, check the tag against the upstream release it was built from.

List webhook generators, the Secrets they reference, and the URL they send to:

kubectl get webhooks.generators.external-secrets.io -A -o json | jq -r '
  .items[]
  | .metadata.namespace as $ns
  | .spec.url as $url
  | (.spec.secrets // [])[]
  | "\($ns)  secret=\(.secretRef.name)  url=\($url)"'

Then check whether each referenced Secret actually carries the label:

kubectl get secret webhook-credentials -n team-a \
  -o jsonpath='{.metadata.labels.external-secrets\.io/type}{"\n"}'

An empty result on a Secret that a generator references is the pattern this bug allowed. On a fixed version that generator would fail. On an affected version it would succeed and send the data out.

What to do now

  1. Upgrade ESO to v1.3.2 or later. If you're on a recent release line, you already have the fix. Confirm the running image, not the chart value in Git.
  2. Audit every webhook generator with the query above. Any generator that references an unlabeled Secret, or that sends to a URL outside your organization, needs an owner and an explanation.
  3. If you find one you can't explain, rotate the referenced Secret and check your egress logs for traffic from the ESO controller pods to that URL.
  4. Tighten RBAC on generator kinds. Limit who can create Webhook resources in generators.external-secrets.io/v1alpha1. The advisory lists this, plus disabling webhook generators if you don't use them, as mitigations.
  5. Add an admission policy that rejects webhook generators whose referenced Secrets lack the external-secrets.io/type=webhook label. The advisory suggests Gatekeeper or Kyverno for this. It's a second layer if a similar bug comes back.
  6. Restrict controller egress. The advisory recommends an allowlist for outbound traffic from ESO controller pods, through a NetworkPolicy or service mesh egress policy. A secrets controller rarely needs to reach arbitrary hosts.

Why it matters

Secret managers in Kubernetes run with wide read access by design, and they protect that access with small checks like this label. When one of those checks fails silently, nothing looks wrong. The generator works, the ExternalSecret syncs, and the only evidence is an outbound request you weren't watching.

The timing is the other lesson. A fix released in February with an advisory in October means dependency scanners had nothing to flag for eight months. Teams that keep controllers current on a schedule were covered anyway. Teams that wait for a CVE before upgrading were not. For cluster add-ons that hold credentials, routine upgrades are part of the security control, not just maintenance.

Try it yourself

Run the generator query against one cluster and build a three-column list: generator, referenced Secret, destination URL. Mark any row where the Secret has no external-secrets.io/type: webhook label or the URL isn't one you recognize. Then write a NetworkPolicy for the ESO namespace that allows only the destinations on your list and apply it in staging.

Quick check

What is the label a Secret needs before ESO's webhook code may read it?

external-secrets.io/type: webhook. On fixed versions, a webhook generator or provider that references a Secret without it fails with the "secret does not contain needed label" error.

Which ESO versions are affected by CVE-2026-26287?

Versions from 0.10.0 up to, but not including, 1.3.2. The fix is in 1.3.2, released on 3 February 2026.

Why does this bug matter even if users can't read Secrets directly?

ESO's controller reads Secrets with its own service account. If a user can create a webhook generator that references a Secret, the broken label check let the controller fetch it and send it to the user's chosen URL, bypassing the RBAC rule that stopped the user reading it.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.