Skip to content

fix(hooks): bound OCI hook stdout/stderr capture to avoid OOM#813

Open
Atishyy27 wants to merge 1 commit into
urunc-dev:mainfrom
Atishyy27:fix/797-bound-hook-output
Open

fix(hooks): bound OCI hook stdout/stderr capture to avoid OOM#813
Atishyy27 wants to merge 1 commit into
urunc-dev:mainfrom
Atishyy27:fix/797-bound-hook-output

Conversation

@Atishyy27

Copy link
Copy Markdown

Problem

Closes #797.

executeHook captures a hook's stdout and stderr into plain bytes.Buffer values:

var stdout, stderr bytes.Buffer
...
cmd.Stdout = &stdout
cmd.Stderr = &stderr

bytes.Buffer grows to hold everything written to it. A prestart/poststart/etc. hook that emits a large amount of data — by accident or malice — is buffered entirely in memory even though the output is only ever used to build an error string. That is an unbounded allocation and a potential OOM.

Fix

Introduce limitedBuffer, an io.Writer that keeps at most maxHookOutput (1 MiB) per stream and discards the rest, flagging the result as truncated:

  • Retains the first maxHookOutput bytes, appends ... [output truncated] when it drops data.
  • Always returns len(p), nil from Write, so exec's internal io.Copy never fails with ErrShortWrite and the hook process is neither blocked nor killed with EPIPE.

Tests

TestLimitedBufferCapsOutput covers: under-limit (kept verbatim), exact-limit (not marked truncated), a single oversized write (capped, full length still reported), and a flood of writes (stays bounded at the cap).

Verification

go build, go vet and test compilation pass (cross-compiled to linux/amd64); the limitedBuffer behaviour was also run directly (oversized write → n reported = 10, retained = 4; 10 KB flood → retained = 5 with full length reported). CI runs the full suite on Linux.

executeHook captured a hook's stdout and stderr into plain bytes.Buffer
values, which grow without limit. A hook that streams a large amount of
data (accidentally or maliciously) could therefore exhaust urunc's
memory, since the captured output is held entirely in RAM only to build
an error message.

Replace the buffers with limitedBuffer, an io.Writer that retains at
most maxHookOutput (1 MiB) per stream and discards the rest, marking the
output as truncated. It always reports the full slice as written so the
hook process is never blocked or killed with a short-write/EPIPE error.
Add unit tests for the under-limit, exact-limit, single-oversized and
repeated-write cases.

Fixes urunc-dev#797
@netlify

netlify Bot commented Jul 8, 2026

Copy link
Copy Markdown

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit e32f98e
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/6a4ec0b5bb2fd300075c2602

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unbounded memory allocation (OOM) during OCI hook execution

1 participant