The Kubernetes admission webhook handler reads the entire request body using io.ReadAll(r.Body) without any size limit. Any client that can reach the webhook port within the cluster can send a multi-GB payload, causing the skipper process to exhaust memory and be OOM-killed. This disrupts all Kubernetes admission control, potentially blocking all pod creation and updates.
// dataclients/kubernetes/admission/admission.go:76
body, err := io.ReadAll(r.Body) // <-- NO SIZE LIMIT
if err != nil {
log.Errorf("Failed to read request: %v", err)
w.WriteHeader(http.StatusInternalServerError)
invalidRequests.WithLabelValues(admitterName).Inc()
return
}
var review admissionReview
err = json.Unmarshal(body, &review)
For comparison, the OPA filter has a body size limit:
// filters/openpolicyagent/openpolicyagent.go:68-70
const DefaultMaxRequestBodySize = 1 << 20 // 1MB
// OPA uses a bufferedBodyReader with size limits
:9443/admission or configured path)POST /admission HTTP/1.1, Content-Type: application/json with a multi-GB request bodyio.ReadAll(r.Body) allocates unbounded memory for the entire bodyDefaultMaxRequestBodySize (1MB) and semaphore-based memory limit; admission handler has neither| File | Lines | Description |
|---|---|---|
dataclients/kubernetes/admission/admission.go |
76 | io.ReadAll(r.Body) without size limit |
filters/openpolicyagent/openpolicyagent.go |
68-70 | OPA filter has DefaultMaxRequestBodySize = 1MB |
filters/openpolicyagent/openpolicyagent.go |
1333-1336 | OPA uses bufferedBodyReader with size limits |
dataclients/kubernetes/admission/admission_test.go exists but does not test body size limitsThe admission webhook handler reads the entire request body using io.ReadAll(r.Body) without a size limit. An attacker with in-cluster network access and a valid Kubernetes client certificate can send a multi-GB payload to the webhook endpoint, causing the skipper process to exhaust memory and be OOM-killed. This disrupts admission control for Ingress and RouteGroup resources until the process is automatically restarted by the kubelet.
Scope of impact: Ingress and RouteGroup admission only — not pod creation or other admission controllers.
Recovery: Kubernetes automatically restarts the OOM-killed process, limiting downtime.
Prerequisites: (1) In-cluster network access to the webhook port, (2) valid Kubernetes client certificate.
http.MaxBytesReader or equivalent body size limit before io.ReadAllDefaultMaxRequestBodySize and use a buffered reader with size limits--admission-max-body-size flag{
"cwe_ids": [
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-17T18:14:08Z",
"nvd_published_at": null,
"severity": "MODERATE"
}