
Table of contents
17
By Salman Khan, OSCP+, Founder of XHack, SRT (Synack Red Team member)
Read this in 30 seconds: CVE-2026-100706 lets a tenant who can create a namespaced Kyverno policy make Kyverno act on the tenant’s behalf with its own powerful identity, and climb from one namespace to cluster admin.
- The trick is an encoded
... A namespace check ran before the path was decoded, so%2e%2ewalked around it. Kyverno 1.19.1 decodes first.- The fix is 16 days older than the CVE. Kyverno shipped 1.19.1 and published the advisory on September 10. The CVE record appeared on September 26, so scanners keyed to CVE IDs may not have flagged it yet.
- It is the second fence to fail this way. CVE-2026-22039, fixed in January, was the same kind of bug. This one is a bypass of the fix.
- It needs a tenant, not a stranger. The attacker needs permission to create Kyverno policies in their own namespace, so shared, multi-tenant clusters are the ones at risk.
- Nothing is reported exploited. But the advisory includes a full reproduction, so treat the technique as public.
A policy engine is supposed to stop people from doing things. Here, the engine did the thing for them.
Kyverno checks and changes Kubernetes objects as they are created. To do that, it runs with broad permissions. CVE-2026-100706 is what happens when a low-privilege tenant can steer those permissions through a policy, and the safety check on that path has a gap.
Here is how the bug works, what an attacker can reach, and how to check your own clusters.

Kyverno is a policy engine for Kubernetes. You write rules such as “no privileged containers” or “every pod needs a label”, and Kyverno enforces them when objects are created.
It comes in two scopes. A ClusterPolicy applies everywhere and is written by admins. A namespaced Policy lives in one namespace, so platform teams often let each team manage its own.
Some policies fetch data at run time through an apiCall context entry, which asks the Kubernetes API for information. That call is made by Kyverno’s own admission controller identity, not the tenant’s. That is the detail this bug abuses.
Here is the description in NVD:
“kyverno before 1.19.1 fails to properly validate URL-encoded path segments in Policy apiCall urlPath, allowing namespace tenants to bypass the per-namespace clamp and create objects in other namespaces as the admission-controller ServiceAccount.”
The record adds that this can mean creating cluster-wide MutatingWebhookConfiguration objects, or PolicyException objects in the kyverno namespace, “enabling privilege escalation to cluster admin.”
The facts to keep:
NVD had not analyzed the record when we checked, so its status still reads “Received.”
When a namespaced policy makes an apiCall, Kyverno is supposed to confine it to that policy’s own namespace. That confinement is what the record calls the “clamp.”
The clamp cleaned the request path and checked which namespace it named. The problem was the order of operations. It checked first and decoded later. A path segment written as %2e%2e is not recognized as .. by that check, so the request looked like it stayed in the tenant’s namespace. The Kubernetes API server then decoded the same text, and the path walked out.
The public fix, commit 7ac176a, states the repair in its own comment: “Decode percent-encoded characters (e.g., %2e%2e -> ..) before normalizing to prevent path traversal bypasses using encoded dot-segments.” It also adds a namespace-scoped resource restriction.

This is our reading of the public commit and advisory, and we have not reproduced the attack.
The advisory describes two routes. We are summarizing them, not reproducing them.
Route A: a cluster-wide webhook. The tenant makes Kyverno create a mutating webhook that sees every pod creation in the cluster. The advisory then shows that webhook being used to change the identity of a kube-system pod to a controller that can edit cluster roles, and to widen one role until every authenticated user is cluster admin. This route works with default Helm values.
Route B: switching off a policy. The tenant makes Kyverno create a PolicyException in its own kyverno namespace, which the tenant cannot write to directly. The exception disables an enforcing policy for the tenant’s namespace, so workloads the policy used to block are admitted. This needs the PolicyException feature enabled and confined to the kyverno namespace, which the advisory calls the recommended hardened setup.
The preconditions are what limit the risk. The attacker must be a namespace tenant with permission to create Kyverno policies in their own namespace, plus the built-in editor role there. A random user on the internet cannot do this. A developer with a namespace on a shared cluster can.
That is why the danger is concentrated in platform setups: internal developer platforms, shared clusters and hosted environments where many teams or customers share one control plane.
CVE-2026-100706 is a repeat of an earlier failure, which is why it deserves attention.
| Date | What happened |
|---|---|
| Jan 27, 2026 | Advisory for CVE-2026-22039: any user who can create a namespaced Policy can make Kyverno call the API as itself. Fixed in 1.16.3 and 1.15.3. |
| Aug 20, 2026 | Kyverno 1.19.0 ships |
| Aug 26, 2026 | A fix for this bypass is merged in Kyverno’s public repository, in a commit covering three advisories |
| Sep 10, 2026 | Kyverno 1.19.1 and the advisories are published, with no CVE ID yet |
| Sep 26, 2026 | The CVE record for CVE-2026-100706 appears in NVD |

The January bug was the absence of any namespace limit. Our reading is that the fix added the clamp, and CVE-2026-100706 goes around that clamp. A sibling advisory from the same fix, GHSA-c5qq-7g2q-cpqp, rates 7.7 and covers using the same encoding trick to read other namespaces.
Two lessons follow. A check is only as good as the moment it runs, and a fix for a boundary bug deserves a second look at every way of writing the same path.
The gap between the fix and the CVE matters in practice. From September 10 to September 26, the fix was public, but anything that alerts on CVE IDs had nothing to alert on.
You are only open to CVE-2026-100706 if all three of these are true:
kubectl -n kyverno get deploy -o wide
kubectl auth can-i create policies.kyverno.io -n <tenant-namespace> --as=system:serviceaccount:<tenant-namespace>:<tenant-sa>
If your tenants cannot create Kyverno Policy objects, you are not exposed to this path. That is one RBAC rule, and it is worth removing even after you patch.
Check what a CVE-2026-100706 attacker could have created as Kyverno:
kubectl get mutatingwebhookconfigurations
kubectl get policyexceptions -A
kubectl get clusterrole system:basic-user -o yaml
Look for:
kyverno namespace that nobody on your platform team wrote.system:basic-user. It should be a small role. A rule that grants everything to everyone is the end state of Route A.kubectl get policies -A -o yaml | grep -i -E '%2e|\.\.'
Also review your API server audit logs for Kyverno’s service account creating webhook configurations or policy exceptions. That is the trace both routes leave.
The interesting question in a Kubernetes test is not “is there a bug.” It is “what can a tenant reach.” A namespace tenant becoming cluster admin is exactly the finding a cloud and Kubernetes penetration test is built to look for.
We would confirm the version, map who holds permission to create policies, and test the fence between tenants on a staging cluster that matches production. We would not run the public reproduction against a live production cluster, because it changes cluster-wide objects and it grants admin. That is the kind of testing our human testers and AI agents do on cloud infrastructure, and your data stays on your own machine while we do it.
Our guides to cloud infrastructure penetration testing and cloud misconfiguration exploits cover the wider ground.
CVE-2026-100706 is a privilege escalation in Kyverno before 1.19.1. A namespace tenant who can create a namespaced Policy can use percent-encoded path segments in an apiCall to bypass Kyverno’s namespace check and create cluster-wide objects as Kyverno’s own service account, which can lead to cluster admin.
No exploitation of CVE-2026-100706 has been reported. The GitHub advisory includes a step-by-step reproduction, so the technique is public and worth patching quickly.
Everything before 1.19.1. The advisory lists 1.19.1 as the only patched version.
Kyverno published the fix and the GitHub advisory on September 10 without a CVE ID. The CVE record was created on September 26 by VulnCheck, acting as the numbering authority. Tools that key off CVE IDs would not have flagged it during those 16 days.
Clusters where people other than admins can create Kyverno Policy objects, such as shared platform clusters, internal developer platforms and hosted environments. If only admins write policies, the attacker needs another way in.
Upgrade Kyverno to 1.19.1 or later, remove tenant permission to create Kyverno policies where it is not needed, and check for unexpected webhooks, policy exceptions and changes to the system:basic-user role.
CVE-2026-100706 is a small ordering mistake with a very large ending: check the path, then decode it, and a tenant walks out of their namespace and into the cluster. The fix is a version bump, and the first job is to find out who in your clusters can write policies.
Upgrade Kyverno, tighten who can create policies, and look for the objects that should not exist. If you find none, you have lost an hour. If you find one, you found it first.
Categories
Related articles