Skip to content

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

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

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.

@netlify

netlify Bot commented Jul 8, 2026

Copy link
Copy Markdown

Deploy Preview for urunc canceled.

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

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

Signed-off-by: Atishyy27 <142108881+Atishyy27@users.noreply.github.com>
@Atishyy27
Atishyy27 force-pushed the fix/797-bound-hook-output branch from e32f98e to ad792be Compare July 9, 2026 07:08
@cmainas

cmainas commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Hello @Atishyy27 ,

please read the contribution guide.

@cmainas cmainas added the invalid This doesn't seem right label Jul 9, 2026
@Atishyy27 Atishyy27 closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid This doesn't seem right

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unbounded memory allocation (OOM) during OCI hook execution

2 participants