Summary
The EventListener reads the entire request body into memory with no size limit via io.ReadAll(request.Body) at two call sites:
pkg/sink/sink.go:153
pkg/sink/validate_payload.go:29
An attacker (or misbehaving webhook sender) streaming large payloads can exhaust the pod's memory, causing OOM kills. With memory limits set (standard for production), sustained large requests can keep the pod in CrashLoopBackOff.
The existing ReadTimeout (default 5s) does not mitigate this — in-cluster, data arrives fast enough to OOM the pod well within the timeout window.
Proposed Fix
Replace bare io.ReadAll with http.MaxBytesReader at both call sites, with a default cap of 3 MiB. This:
- Rejects oversized requests with
413 Request Entity Too Large
- Closes the connection immediately rather than draining the stream
3 MiB provides ample headroom — typical webhook payloads from GitHub, GitLab, and Bitbucket are 5–100 KB; the largest observed are ~1 MB.
The limit should be configurable via an EventListener flag (e.g. --el-max-body-size).
Example
// Before
event, err := io.ReadAll(request.Body)
// After
request.Body = http.MaxBytesReader(response, request.Body, maxBodySize)
event, err := io.ReadAll(request.Body)
Summary
The EventListener reads the entire request body into memory with no size limit via
io.ReadAll(request.Body)at two call sites:pkg/sink/sink.go:153pkg/sink/validate_payload.go:29An attacker (or misbehaving webhook sender) streaming large payloads can exhaust the pod's memory, causing OOM kills. With memory limits set (standard for production), sustained large requests can keep the pod in CrashLoopBackOff.
The existing
ReadTimeout(default 5s) does not mitigate this — in-cluster, data arrives fast enough to OOM the pod well within the timeout window.Proposed Fix
Replace bare
io.ReadAllwithhttp.MaxBytesReaderat both call sites, with a default cap of 3 MiB. This:413 Request Entity Too Large3 MiB provides ample headroom — typical webhook payloads from GitHub, GitLab, and Bitbucket are 5–100 KB; the largest observed are ~1 MB.
The limit should be configurable via an EventListener flag (e.g.
--el-max-body-size).Example