Skip to content

CVE-2026-41485 - Kyverno forEach mutation panic DoS

Kyverno versions 1.13.0 through 1.16.3 and 1.17.0-rc.1 through 1.17.1 can panic when a legacy-engine forEach mutation rule resolves patchesJson6902 to nil and Kyverno performs an unchecked Go type assertion. A user who can create a namespaced Policy can crash the cluster-wide background controller into a persistent CrashLoopBackOff. A user who can create a matching ClusterPolicy can also cause admission webhook connections to drop for matched resource operations.

The impact is a Kubernetes control-plane availability failure. Background processing for generate rules, mutateExisting rules, cleanup, and related Kyverno work can stop across the cluster until the vulnerable version is patched and the poisoned policy or UpdateRequest queue state is removed.

This is relevant to SecurityRecipes because policy engines are part of the secure context and agentic control plane: if a tenant, workflow, or agent can write policy definitions, malformed policy must fail closed without taking the admission or background-control layer down.

Affected versions

  • Vulnerable: Kyverno >=1.13.0, <1.16.4
  • Fixed: Kyverno 1.16.4+ on the 1.16 line
  • Vulnerable: Kyverno >=1.17.0-rc.1, <1.17.2
  • Fixed: Kyverno 1.17.2+ on the 1.17 line
  • Affected package: github.com/kyverno/kyverno
  • High-risk condition: users, tenants, CI jobs, agents, or platform teams can create or update Kyverno Policy or ClusterPolicy resources that use legacy-engine mutate.foreach rules.
  • Not affected by this specific bug: CEL-based Kyverno policies.

Indicator-of-exposure

  • The repository deploys Kyverno through Helm, Kustomize, raw manifests, Terraform, Flux, Argo CD, an operator, cluster bootstrap scripts, or a platform image.
  • Resolved Kyverno controller images, charts, app manifests, SBOMs, or runtime inventory show 1.13.0 through 1.16.3 or 1.17.0-rc.1 through 1.17.1.
  • Developers, tenants, namespace owners, CI workflows, GitOps repos, support teams, agents, or self-service platforms can create namespaced Policy resources.
  • Cluster-admin automation, policy-as-code repos, or platform agents can create ClusterPolicy resources.
  • Existing policies use mutate, foreach, patchesJson6902, patchStrategicMerge, mutateExisting, or generated UpdateRequest resources.
  • Kyverno background-controller pods have recently restarted or entered CrashLoopBackOff, especially with logs mentioning interface conversion: interface {} is nil, not string.

Quick checks:

rg -n "kyverno|ghcr\\.io/kyverno/kyverno|kyverno.io|ClusterPolicy|kind: Policy|mutateExisting|foreach|patchesJson6902|UpdateRequest" .
rg -n "kyverno/kyverno|app.kubernetes.io/name: kyverno|background-controller|admission-controller" charts deploy k8s helm terraform .github . 2>/dev/null
helm list -A | grep -Ei 'kyverno'
kubectl -n kyverno get deploy,pods -o wide
kubectl -n kyverno get pods -l app.kubernetes.io/component=background-controller
kubectl get policy,clusterpolicy -A -o yaml | grep -Ei 'foreach|patchesJson6902|mutateExisting'
kubectl get updaterequest -A

Remediation strategy

  • Upgrade every controlled Kyverno deployment to 1.16.4+ on the 1.16 line or 1.17.2+ on the 1.17 line. Prefer the latest supported patch release for the deployed minor line.
  • Regenerate Helm locks, rendered manifests, Kustomize output, GitOps bootstrap artifacts, image digests, SBOMs, policy inventory, and deployment evidence.
  • Temporarily restrict creation and update of Kyverno Policy and ClusterPolicy resources while vulnerable controllers are still running.
  • Audit legacy-engine mutate.foreach rules and move feasible policies to CEL or add static policy checks that reject patchesJson6902 values that can resolve to non-strings.
  • If a cluster is already in a crash loop, remove the offending Policy, ClusterPolicy, and poisoned UpdateRequest resources only through the normal cluster incident process, with the owning platform team involved.
  • Add a non-production regression fixture that proves the repository rejects unsafe forEach mutation patterns without applying panic-triggering payloads to shared clusters.

The prompt

Model context: this prompt was generated by GPT 5.5 Extra High reasoning.

You are remediating CVE-2026-41485 (Kyverno forEach mutation panic denial of
service). Produce exactly one output:

- A reviewer-ready PR/change request that upgrades Kyverno, contains vulnerable
  policy creation paths, adds safe regression coverage, and documents operator
  cleanup, or
- TRIAGE.md if this repository does not own an affected Kyverno deployment,
  policy-as-code surface, or safe patch path.

## Rules

- Scope only CVE-2026-41485 / GHSA-fpjq-c37h-cqcv and directly related Kyverno
  policy-engine containment.
- Treat cluster kubeconfigs, service account tokens, admission webhook
  credentials, policy exception data, tenant policy repos, controller logs, and
  incident evidence as sensitive.
- Do not apply panic-triggering Policy or ClusterPolicy payloads to production,
  shared, customer, or developer clusters.
- Do not delete live `Policy`, `ClusterPolicy`, or `UpdateRequest` resources
  unless this repository explicitly owns the incident/runbook path and the
  change is framed as an operator action.
- Do not disable Kyverno admission, background processing, or fail-closed
  controls as a silent workaround.
- Do not auto-merge.

## Steps

1. Inventory every Kyverno asset controlled by this repository:
   Helm charts, values files, `Chart.lock`, Kustomize overlays, raw manifests,
   Terraform, Flux/Argo CD applications, operators, cluster bootstrap scripts,
   image tags/digests, SBOMs, policy-as-code directories, CI workflows, and
   runbooks.
2. Determine every resolved Kyverno version. A target is vulnerable if it
   resolves to:
   - `>=1.13.0, <1.16.4`;
   - `>=1.17.0-rc.1, <1.17.2`.
3. Search controlled policies and generated artifacts for legacy mutation
   shapes:
   - `kind: Policy`;
   - `kind: ClusterPolicy`;
   - `mutate`;
   - `foreach`;
   - `patchesJson6902`;
   - `patchStrategicMerge`;
   - `mutateExisting`;
   - `UpdateRequest`.
4. Map who can create or update policy resources:
   namespace users, tenant roles, CI jobs, GitOps controllers, support groups,
   platform agents, agentic remediation workflows, and cluster-admin
   automation.
5. If this repository does not deploy Kyverno and does not control Kyverno
   policy-as-code, stop with `TRIAGE.md` naming the files checked, the likely
   runtime owner, and the required fixed versions `1.16.4+` or `1.17.2+`.
6. Upgrade Kyverno to a fixed version using the repository's normal delivery
   mechanism. Regenerate lockfiles, rendered manifests, image digests, SBOMs,
   deployment evidence, and policy inventory.
7. Add temporary containment for non-atomic rollouts:
   - restrict `Policy` and `ClusterPolicy` creation/update to trusted platform
     owners until patched controllers are deployed;
   - pause self-service policy onboarding or agent-created policy changes;
   - add admission or CI checks that block vulnerable `mutate.foreach`
     `patchesJson6902` patterns before they reach a cluster;
   - document that CEL-based policies are preferred when they cover the use
     case.
8. Add safe regression coverage without crashing real controllers:
   - static tests that reject `patchesJson6902` values sourced entirely from
     unresolved substitutions such as `{{ element.nonexistent }}`;
   - policy-lint fixtures for `foreach` mutation rules;
   - version checks proving rendered Kyverno deployments resolve to fixed
     versions;
   - RBAC tests or policy checks showing only trusted owners can create or
     update high-impact `Policy` and `ClusterPolicy` resources.
9. Add an operator cleanup section named `CVE-2026-41485 operator actions` to
   the PR body or `TRIAGE.md`:
   - Kyverno versions before and after the change;
   - whether legacy `mutate.foreach` rules are present;
   - whether namespaced users, tenants, CI jobs, or agents can create Kyverno
     policies;
   - whether `UpdateRequest` resources need inspection or cleanup;
   - how to identify a poisoned policy without reapplying the exploit;
   - which background-controller and admission-controller logs should be
     reviewed;
   - what rollback/restore steps preserve fail-closed behavior.
10. Run relevant validation: Helm dependency update, Helm template, Kustomize
    build, Terraform plan, policy lint, Kyverno CLI tests, unit tests,
    integration tests, image build, SBOM refresh, and dependency/security scans
    available in this repository.
11. Use PR title:
    `fix(sec): remediate CVE-2026-41485 in Kyverno policy control plane`.

## Stop conditions

- No Kyverno deployment, Kyverno policy-as-code, or cluster bootstrap artifact
  is controlled by this repository.
- All controlled Kyverno targets already resolve to `1.16.4+` or `1.17.2+`
  and rendered artifacts prove no vulnerable controller remains.
- Upgrading Kyverno requires a platform release train outside this repository.
- Proving exposure would require applying a panic-triggering policy to a live
  or shared cluster.
- Product requirements intentionally let untrusted users or agents create
  arbitrary Kyverno policies; document the risk and require a product/security
  decision.
- Validation fails for unrelated pre-existing reasons; document those failures
  instead of broadening scope.

Verification - what the reviewer looks for

  • No controlled Helm chart, values file, image digest, rendered manifest, SBOM, or deployment target resolves Kyverno to 1.13.0 through 1.16.3 or 1.17.0-rc.1 through 1.17.1.
  • Policy creation/update rights are reviewed for namespace users, tenants, CI jobs, GitOps controllers, support groups, platform agents, and automated remediation workflows.
  • Legacy mutate.foreach rules are inventoried, linted, converted to safer forms where feasible, or explicitly contained.
  • Regression tests use static or isolated fixtures and do not crash production, shared, customer, or developer clusters.
  • Operator actions explain how to inspect and clean poisoned UpdateRequest resources without weakening admission controls.

Watch for

  • Updating the Kyverno chart source while committed rendered manifests or Argo CD app-of-apps overlays still point at a vulnerable controller image.
  • Assuming namespace-scoped policy creation is low risk because it lacks cluster-admin permissions. This advisory can turn a namespaced Policy into cluster-wide background-controller failure.
  • Disabling Kyverno webhooks or changing failure policy as a workaround without an incident owner and rollback plan.
  • Tests that reproduce the panic by applying exploit manifests to real clusters.
  • Missing agent-created or CI-created policy paths because only human RBAC bindings were reviewed.

References