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-2HW4-C9M4-F2FJ

CVE-2026-54462: Unbounded Request-Body Memory Exhaustion in Knative Admission Webhooks

Alon Barad
Alon Barad
Software Engineer

Oct 29, 2026·10 min read·2 visits

Executive Summary (TL;DR)

The knative.dev/pkg admission webhook server fails to restrict HTTP request body sizes before buffering and decoding JSON payloads. A single oversized HTTP POST request from a pod-network client gets amplified by 4.5x in memory, triggering a container OOM-kill and disrupting cluster-wide resource admission across downstream projects like Knative, Tekton, KEDA, and Sigstore.

An uncontrolled resource consumption vulnerability in the knative.dev/pkg/webhook package allows network-adjacent attackers within a Kubernetes cluster to trigger Out-Of-Memory (OOM) terminations of admission controller pods. The admission webhook HTTP server processes incoming AdmissionReview requests through an io.TeeReader and json.Decoder pipeline without enforcing an upper bound on request body size. Due to internal buffer reallocation mechanics, incoming payloads experience a 4.5x memory amplification factor. Because knative.dev/pkg provides the shared webhook server foundation for numerous cloud-native projects—including Knative Serving, Knative Eventing, Tekton, KEDA, Sigstore Policy Controller, and Kpack—exploitation can halt resource admission across entire Kubernetes clusters or bypass critical security validation policies.

Vulnerability Overview

The knative.dev/pkg repository provides foundational Go packages shared across the Knative ecosystem and external cloud-native projects. Among these components is knative.dev/pkg/webhook, which implements a standardized HTTP server for handling Kubernetes Mutating and Validating Admission Webhooks. In Kubernetes architectures, the API server dispatches AdmissionReview requests via HTTPS POST to these registered webhook endpoints whenever matching cluster resources are created, updated, or deleted.

Prior to pseudo-version 0.0.0-20260531000007-52dbd5ece63f, the webhook HTTP handler processes incoming request bodies without enforcing a maximum byte limit. Specifically, the admissionHandler function reads directly from the unthrottled http.Request.Body stream, duplicating the byte stream into an in-memory buffer while simultaneously unmarshaling the JSON structure.

This flaw is classified under CWE-770 (Allocation of Resources Without Limits or Throttling). Any workload or pod within the Kubernetes cluster capable of routing TCP traffic to the webhook service port can transmit an arbitrarily large HTTP POST payload. Because the webhook server does not wrap the request body in an http.MaxBytesReader or io.LimitReader, it continues allocating heap memory until the underlying container exceeds its configured Kubernetes cgroup memory limit and is terminated by the Linux kernel Out-Of-Memory (OOM) killer.

The architectural significance of this vulnerability stems from the widespread adoption of knative.dev/pkg/webhook as an upstream library. Downstream controllers—including Knative Serving, Knative Eventing, Tekton Pipelines, Tekton Triggers, KEDA, Sigstore Policy Controller, and Kpack—directly inherit this vulnerable HTTP handler. Consequently, a single unbounded request can neutralize admission control or policy enforcement across diverse cloud-native infrastructure components.

Root Cause Analysis

The vulnerability originates in webhook/admission.go within the admissionHandler method, which serves as the primary HTTP handler for processing incoming Kubernetes admission requests. When an HTTP request arrives at the webhook endpoint, the handler initializes an admissionv1.AdmissionReview struct and a bytes.Buffer instance named bodyBuffer. The handler then constructs a streaming pipeline using json.NewDecoder(io.TeeReader(r.Body, &bodyBuffer)).Decode(&review).

The root cause is the absence of an input size boundary on r.Body combined with the memory allocation characteristics of io.TeeReader and encoding/json.Decoder. As json.Decoder pulls bytes from the io.TeeReader to parse JSON tokens, io.TeeReader synchronously writes an identical copy of every byte read into bodyBuffer so the raw payload remains available for subsequent logging or error reporting. Neither the HTTP multiplexer nor the admission handler verifies the Content-Length header or restricts the total bytes read from the underlying TCP socket.

This design triggers severe memory amplification due to Go slice growth semantics and JSON lexical buffering. As bodyBuffer (bytes.Buffer) ingests data from the io.TeeReader, its internal byte slice repeatedly reaches capacity and must be reallocated. During slice reallocation, the Go runtime allocates a new underlying array typically double the size of the previous capacity and copies the existing contents over. At the moment of reallocation, the heap simultaneously holds both the old buffer (1x) and the newly allocated buffer (2x), resulting in a transient memory footprint of 3x the streamed payload size.

Concurrently, json.NewDecoder maintains its own internal read buffer (dec.buf), which also dynamically expands as it scans continuous JSON tokens or long string literals. Empirical benchmark testing against the vulnerable handler demonstrates that streaming a 2 GiB payload increases HeapAlloc from a baseline of 0.32 MiB to a peak of 9,217.38 MiB (~9.00 GiB). This represents a 4.50x memory amplification ratio relative to the transmitted payload size.

Code Analysis

In the unpatched codebase, the vulnerable sink resides in webhook/admission.go. The handler accepts the raw *http.Request and immediately begins decoding from r.Body without prior sanitization or size wrapping:

// Location: webhook/admission.go (lines 109-117)
review := admissionv1.AdmissionReview{}
var bodyBuffer bytes.Buffer
// VULNERABLE: r.Body is unbounded. io.TeeReader duplicates all bytes read
// by json.NewDecoder into bodyBuffer without limit.
if err := json.NewDecoder(io.TeeReader(r.Body, &bodyBuffer)).Decode(&review); err != nil {
    http.Error(w, fmt.Sprintf("could not decode body: %v", err), http.StatusBadRequest)
    return
}

Rather than modifying individual sub-handlers such as admissionHandler, the maintainers addressed the issue globally at the webhook server entry point in webhook/webhook.go via commit 52dbd5ece63fe6d2d340ecbebec160550f460818 (PR #3363). The patch modifies the top-level ServeHTTP method on the Webhook struct:

--- a/webhook/webhook.go
+++ b/webhook/webhook.go
@@ -395,7 +395,9 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	wh.mux.ServeHTTP(w, r)
+	const MaxBodySize = 3 * 1024 * 1024 // 3 MiB
+	h := http.MaxBytesHandler(&wh.mux, MaxBodySize)
+	h.ServeHTTP(w, r)
 }

The patch introduces a constant MaxBodySize set to 3 * 1024 * 1024 bytes (3 MiB) and wraps the internal router (&wh.mux) with the standard library's http.MaxBytesHandler. Under the hood, http.MaxBytesHandler replaces r.Body with an http.MaxBytesReader(w, r.Body, MaxBodySize) before passing the request down to wh.mux.ServeHTTP.

This remediation is complete and architecturally sound. By placing http.MaxBytesHandler in Webhook.ServeHTTP, all registered handlers on the webhook multiplexer—including mutating admission, validating admission, and conversion endpoints—are automatically protected. When a client streams a payload exceeding 3 MiB, http.MaxBytesReader halts further reads from the socket, returns an error to json.Decoder, and instructs the HTTP response writer to close the connection. Furthermore, the 3 MiB threshold accommodates legitimate Kubernetes AdmissionReview objects, as Kubernetes etcd and the API server enforce a default maximum serialized resource size of 1.5 MiB to 2 MiB.

Exploitation

Exploiting CVE-2026-54462 requires network connectivity to the target admission webhook's listening port (typically TCP port 8443). In standard Kubernetes deployments, admission webhooks are exposed internally via a ClusterIP Service so the Kubernetes API server can reach them. Unless restricted by strict Kubernetes NetworkPolicy definitions or mutual TLS (mTLS) client certificate verification at the TLS termination layer, any pod running on the cluster network can establish a connection to the webhook Service IP.

Although the webhook server runs over TLS, it typically uses a server certificate signed by an internal cluster CA or self-signed secret, and by default does not enforce tls.RequireAndVerifyClientCert unless explicitly configured. An attacker operating from a compromised pod or a tenant namespace in a multitenant cluster can initiate a TLS handshake with InsecureSkipVerify: true and send an HTTP POST request directly to the admission path (such as /defaulting, /validating, or /).

To trigger the OOM condition, the attacker does not need to construct a valid AdmissionReview JSON structure. Instead, the attacker initiates a streaming HTTP POST request containing a valid JSON opening token (such as {"a":") followed by a continuous stream of arbitrary characters (e.g., repeated a bytes). Because json.Decoder must read until the closing quote of the string literal to complete token lexing, both json.Decoder and bodyBuffer continuously accumulate the incoming stream in heap memory.

Due to the 4.5x memory amplification factor, the bandwidth required from the attacker is modest. A standard Kubernetes admission controller pod is frequently provisioned with a memory limit (resources.limits.memory) between 256 MiB and 512 MiB. Transmitting a single payload of approximately 115 MiB to 128 MiB over the local cluster network is sufficient to allocate over 512 MiB of heap memory, exhausting the container cgroup limit within milliseconds and causing the kernel to issue SIGKILL (exit code 137).

> [!NOTE] > This exploitation pattern mirrors related Go admission webhook vulnerabilities across the cloud-native ecosystem, specifically CVE-2026-24514 in ingress-nginx and GHSA-9539-c3xr-w9vm in Kyverno, both of which involved unbounded request body reading leading to pod OOM kills.

Impact Assessment

CVE-2026-54462 is rated Medium severity with a CVSS v3.1 score of 6.5 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H). The vector reflects that the attack occurs over the network (AV:N) with low attack complexity (AC:L) and no user interaction (UI:N), requiring only low privileges (PR:L) representing pod-network access inside the cluster. While there is no direct impact to confidentiality (C:N) or integrity (I:N) from the memory exhaustion itself, the availability impact to the targeted component is high (A:H).

The operational impact on a Kubernetes cluster depends directly on the failurePolicy configured on the MutatingWebhookConfiguration or ValidatingWebhookConfiguration objects managed by the downstream consumer:

  1. failurePolicy: Fail (Cluster-Wide Denial of Service): Most production controllers—including Knative Serving, Tekton Pipelines, and Sigstore Policy Controller—default to failurePolicy: Fail to guarantee that unvalidated or unmutated resources cannot enter the cluster. When an attacker repeatedly OOM-kills the webhook pod (pushing it into CrashLoopBackOff), the Kubernetes API server rejects all CREATE and UPDATE requests for matching resources. In Tekton or Knative environments, this halts CI/CD pipeline execution and serverless deployment scaling. If the webhook intercepts core resources like Pods or Namespaces (common with Sigstore Policy Controller), the attacker effectively paralyzes workload scheduling across the cluster.
  2. failurePolicy: Ignore (Security Policy & Validation Bypass): If an administrator has configured a validating webhook with failurePolicy: Ignore to prioritize cluster uptime, crashing the webhook pod causes the Kubernetes API server to fail open. While the webhook is offline due to OOM termination, an attacker can submit non-compliant or unsigned container workloads that bypass admission validation and mutation.

The scope of affected systems spans a broad segment of the CNCF ecosystem:

Downstream ProjectRepositoryAffected Webhook Functionality
Knative Servingknative/servingValidation and defaulting for Services, Configurations, Revisions, and Routes
Knative Eventingknative/eventingValidation and defaulting for Brokers, Triggers, Channels, and Subscriptions
Tekton Pipelinestektoncd/pipelineAdmission validation and mutation for Pipelines, Tasks, TaskRuns, and PipelineRuns
Tekton Triggerstektoncd/triggersValidation for EventListeners, Triggers, and TriggerBindings
KEDAkedacore/kedaValidation and defaulting for ScaledObjects and ScaledJobs
Sigstore Policy Controllersigstore/policy-controllerContainer image signature verification and ClusterImagePolicy enforcement
Kpackbuildpacks-community/kpackValidation and defaulting for Image and Builder resources

Remediation

Remediation requires updating the knative.dev/pkg Go module dependency to a version containing commit 52dbd5ece63fe6d2d340ecbebec160550f460818 (0.0.0-20260531000007-52dbd5ece63f or later) and rebuilding all downstream admission controller binaries and container images.

For Go developers maintaining downstream controllers or custom webhooks built on knative.dev/pkg/webhook, update the dependency in go.mod using the following commands:

go get knative.dev/pkg@52dbd5ece63fe6d2d340ecbebec160550f460818
go mod tidy

For Kubernetes cluster operators running pre-built releases of Knative, Tekton, KEDA, Sigstore Policy Controller, or Kpack where patched upstream container images are not immediately deployed, the primary compensating control is network isolation via Kubernetes NetworkPolicy. Because only the Kubernetes API server (kube-apiserver) has a legitimate need to communicate with admission webhook pods, operators should block all intra-cluster pod-to-webhook traffic.

Below is an example NetworkPolicy that restricts ingress traffic to the webhook port (8443) so that only the control plane API server CIDR can establish connections:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-webhook-ingress
  namespace: knative-serving # Replace with target controller namespace (e.g., tekton-pipelines, keda)
spec:
  podSelector:
    matchLabels:
      app: webhook # Replace with the specific label selector for the webhook pod
  policyTypes:
    - Ingress
  ingress:
    - from:
        - ipBlock:
            cidr: 10.0.0.10/32 # Replace with the kube-apiserver IP/CIDR
      ports:
        - protocol: TCP
          port: 8443

Additionally, if the webhook deployment supports mutual TLS (mTLS) configuration, enforcing strict client certificate authentication (tls.RequireAndVerifyClientCert) verified against the Kubernetes API server's client CA prevents unauthenticated cluster pods from completing the TLS handshake and reaching the HTTP handler.

Official Patches

KnativeGitHub Security Advisory GHSA-2hw4-c9m4-f2fj
KnativePull Request #3363: Limit the webhook request body size to 3MiB
KnativePatch Commit 52dbd5ece63fe6d2d340ecbebec160550f460818

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.38%
Top 69% most exploited

Affected Systems

knative.dev/pkgKnative ServingKnative EventingTekton PipelinesTekton TriggersKEDASigstore Policy ControllerKpack

Affected Versions Detail

Product
Affected Versions
Fixed Version
knative.dev/pkg
Knative
< 0.0.0-20260531000007-52dbd5ece63f0.0.0-20260531000007-52dbd5ece63f
AttributeDetail
CVE IDCVE-2026-54462 (GHSA-2hw4-c9m4-f2fj)
Vulnerability ClassCWE-770: Allocation of Resources Without Limits or Throttling
CVSS v3.1 Score6.5 Medium (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)
EPSS Score0.38% (31.45th Percentile)
Memory Amplification4.5x transmitted request body size
Primary ImpactAdmission Controller OOM-Kill / Cluster Admission DoS
Patched Version0.0.0-20260531000007-52dbd5ece63f (3 MiB limit)
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

The software allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.

Vulnerability Timeline

Vulnerability verified on github.com/knative/pkg main branch (commit 1ad5a1ce0ee7043081cb50fd1acc6d36a9126844).
2026-05-18
End-to-end verification completed confirming 4.5x memory amplification factor.
2026-05-19
Fix committed via PR #3363 (52dbd5ece63fe6d2d340ecbebec160550f460818) enforcing a 3 MiB request body limit.
2026-05-31
CVE-2026-54462 officially published and updated by GitHub CNA.
2026-10-27
GHSA-2hw4-c9m4-f2fj published in the GitHub Advisory Database.
2026-10-28

References & Sources

  • [1]GitHub Security Advisory: GHSA-2hw4-c9m4-f2fj
  • [2]CVE-2026-54462 Official Record
  • [3]Knative pkg Pull Request #3363
  • [4]Patch Commit 52dbd5ece63fe6d2d340ecbebec160550f460818
  • [5]Knative pkg Repository
Related Vulnerabilities
CVE-2026-24514

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

•about 2 hours ago•CVE-2026-115923
6.5

CVE-2026-115923: Path Traversal and Catalog Rule Bypass in Backstage Catalog Backend

CVE-2026-115923 (GHSA-w658-mh9p-ww8f) is a path traversal and access control bypass vulnerability in Spotify's Backstage developer portal framework, specifically within the @backstage/plugin-catalog-backend package. Prior to patched versions, DefaultCatalogRulesEnforcer evaluated user-supplied URL catalog locations against configured catalog.rules patterns using raw, uncanonicalized strings. Because downstream URL readers canonicalize URLs and resolve dot segments before fetching resources, an authenticated attacker with location registration permissions can supply percent-encoded traversal sequences (such as %2e%2e) to bypass location restrictions and register untrusted catalog entities.

Amit Schendel
Amit Schendel
4 views•9 min read
•about 3 hours ago•CVE-2026-116576
7.8

CVE-2026-116576: OS Command Injection via Unicode Quotation Marks in Node.js systeminformation

CVE-2026-116576 (GHSA-3f7j-7jwc-fxfj) is an OS Command Injection vulnerability (CWE-78) in the Node.js systeminformation library prior to version 5.33.16 on Microsoft Windows. The services() API function dynamically constructs a PowerShell Get-CimInstance command using caller-supplied service names passed through sanitizeShellString(). While the sanitizer strips standard ASCII quotation marks, it permits Unicode typographic quotation marks (U+2018 through U+201E). Because the Windows PowerShell tokenizer recognizes Unicode quotation marks as valid string literal delimiters, an attacker who controls the service name input can break out of the CIM filter string and execute arbitrary PowerShell commands within the security context of the Node.js process.

Alon Barad
Alon Barad
3 views•11 min read
•about 4 hours ago•CVE-2026-116695
5.3

CVE-2026-116695: CSS Sanitizer Bypass via Bad URL Tokenization Differential in Crass

An interpretation conflict vulnerability (CWE-436) exists in the Ruby CSS parser library Crass prior to version 1.0.8. When consuming the remnants of a malformed URL token, the tokenizer erroneously checks the previously consumed character to determine if a valid escape sequence is present. Consequently, a closing parenthesis immediately following an escaped backslash sequence is treated as escaped by Crass, while spec-compliant web browsers treat the closing parenthesis as the end of the bad URL token. Downstream CSS sanitizers such as Sanitize, Loofah, and rails-html-sanitizer that rely on Crass to parse and reserialize untrusted CSS can be bypassed to inject arbitrary CSS declarations, style rules, and external @import directives.

Amit Schendel
Amit Schendel
6 views•11 min read
•about 5 hours ago•CVE-2026-116577
5.3

CVE-2026-116577: Algorithmic Complexity Denial of Service in Tornado HTTP Header Parser

Tornado versions prior to 6.6.0 contain an inefficient algorithmic complexity vulnerability in the HTTP header parser. When processing requests with obsolete line folding (obs-fold), the HTTPHeaders.parse_line method repeatedly concatenates immutable Python strings within a list structure. An unauthenticated remote attacker can send an HTTP request containing thousands of short header continuation lines to trigger quadratic O(N^2) CPU consumption on the main IOLoop thread, starving concurrent connections and resulting in a denial of service.

Alon Barad
Alon Barad
7 views•10 min read
•about 6 hours ago•CVE-2026-116578
2.1

CVE-2026-116578: Open Redirect in Tornado RedirectHandler via URL Normalization and Template Substitution

Tornado versions prior to 6.6.0 contain an open redirect vulnerability (CWE-601) in tornado.web.RedirectHandler. When route templates incorporate regular expression capture groups at the start of a path, directly after a fixed host without a trailing slash, or at the beginning of a destination template, unvalidated URL-decoded parameters allow attackers to manipulate the redirect scheme or network location. Because modern browsers normalize URLs according to the WHATWG specification—treating backslashes as forward slashes and stripping control characters—attackers can bypass naive prefix checks and redirect victims to arbitrary external domains.

Alon Barad
Alon Barad
8 views•11 min read
•about 7 hours ago•CVE-2026-115927
5.3

CVE-2026-115927: Event Loop Blocking and Memory Amplification in Tornado Chunked Transfer Encoding Parser

Tornado versions prior to 6.6.0 contain an uncontrolled resource consumption vulnerability (CWE-400) in the HTTP/1.1 chunked transfer encoding parser. When processing incoming chunked payloads that have already buffered in the socket read buffer, Tornado parses chunks in a tight synchronous loop without yielding to the event loop. Furthermore, non-streaming request handlers and SimpleAsyncHTTPClient store each chunk as a discrete Python bytes object inside a list, inducing an approximately 20-fold memory overhead for 1-byte chunks.

Amit Schendel
Amit Schendel
5 views•11 min read