Skip to content

fix: harden tarball extraction against symlink traversal and stderr OOM - #39

Merged
avrabe merged 1 commit into
mainfrom
fix/tarball-extraction-safety
May 1, 2026
Merged

fix: harden tarball extraction against symlink traversal and stderr OOM#39
avrabe merged 1 commit into
mainfrom
fix/tarball-extraction-safety

Conversation

@avrabe

@avrabe avrabe commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Fixes Bug #15 from docs/agent-fleet/bugs.md (wave-1 Security auditor).

Hardens src/rivet-fetch.js:

  • --no-same-owner --no-same-permissions on tar

  • Drain tar.stdout to prevent pipe-buffer deadlock

  • Cap stderr at 64 KiB

  • Post-extract symlink walk rejects any link escaping destDir

  • 814 tests pass (+8)

  • eslint clean

🤖 Generated with Claude Code

## Why
`src/rivet-fetch.js` invoked `tar -xz --strip-components=1 -C destDir` with
no symlink guard. A malicious PR head ref could include a symlink in the
tarball pointing outside `destDir`; subsequent `runRivetOracle` reads
`rivet.yaml` from that target — a path-traversal vector. Additionally,
unbounded `stderr` accumulation on pathological tar output could OOM the
worker, and `tar.stdout` was piped but never drained — verbose tar output
would block the child.

## What
- Add `--no-same-owner` and `--no-same-permissions` to the tar invocation;
  defensive even though we run as a single user.
- Drain `tar.stdout` (`.resume()`) so a verbose tar can't deadlock on a full
  pipe buffer.
- Cap `stderr` accumulation at 64 KiB; mark the message `(stderr truncated)`
  on overflow.
- Post-extract, walk `destDir` and reject any symlink whose `path.resolve`d
  target escapes the directory. Reject by `fs.unlinkSync` and throwing.
- Export `assertNoEscapingSymlinks` for direct unit-testability.

## Source
Wave-1 Security auditor flagged this as Bug #15 in `docs/agent-fleet/bugs.md`.

## Test plan
- [x] 814 tests pass (was 806; +8 covering: hardening flags applied, stdout
      drained, stderr capped, escaping absolute symlink rejected, escaping
      relative `..` symlink rejected, benign tree accepted, in-bounds
      symlink accepted)
- [x] eslint clean

## Risk & rollout
- Risk: low. The rejected cases are anomalous (escaping symlinks); benign
  archives extract identically.
- Rollout: self-update on merge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe
avrabe merged commit 207e2a0 into main May 1, 2026
5 checks passed
@avrabe
avrabe deleted the fix/tarball-extraction-safety branch May 1, 2026 07:14
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.

1 participant