Outcome
Central sandbox verification remains usable and fail-closed when a repository command or E2E service emits excessive output. Parent memory and retained log files are capped before evidence redaction, while a bounded final diagnostic suffix remains available for review.
Problem
sandboxed_verify.py and sandboxed_web_e2e.py currently use subprocess.PIPE/communicate()-style capture for short-lived commands, which can buffer an unbounded stream in memory. Long-running E2E services write to ordinary files without a quota, and tail_text() reads the entire file before selecting the final lines. A malicious or defective repository process can therefore exhaust runner memory or disk before the redaction boundary executes.
Scope
- add one reusable POSIX bounded-subprocess module that continuously drains stdout/stderr on background threads into fixed-size final-suffix buffers;
- terminate the isolated process group on the first stream overflow;
- redirect neither application file writes nor build artifacts through process-wide
RLIMIT_FSIZE, because that limit would incorrectly constrain every regular file created by the child;
- cap each short-lived command stream at an explicit byte budget and return a stable output-limit result;
- capture long-running backend/frontend combined logs through the same bounded drainer and persist only the bounded rendered suffix;
- read only a bounded suffix from service evidence files using seek-from-end, then preserve the final line limit and redaction;
- retain structured argv,
shell=False, process-group cleanup, timeouts, exit status, output redaction, evidence notes, and environment scrubbing;
- keep a dedicated non-POSIX fail-closed contract rather than silently running without isolated process-group termination;
- add realistic tests with child processes that exceed stdout, stderr, and service-log budgets, plus normal Unicode and partial-codepoint suffix cases;
- maintain 100% statement/branch coverage and complete production docstrings;
- document Python subprocess pipe semantics, CWE-770, NIST SSDF, limitations, and rollback using APA 7 references;
- update
CHANGELOG.md.
Acceptance
- excessive output cannot grow retained per-stream memory or service evidence files beyond the declared budget;
- the parent continuously drains pipes, avoiding child deadlock on full OS pipe buffers;
- output-limit termination has stable exit code 123 and bounded redacted evidence;
- timeout remains 124 and readiness failure remains 125 unless a more specific output limit occurred;
- ordinary commands and services preserve current behavior and may create normal build/test artifacts larger than the output budget;
- exact-head central tests, 100% coverage/docstrings, Secret Scan, Semgrep, CodeQL, Python Security, Security Scan, OpenCode, Noema, CodeRabbit, independent approval, and branch protection pass;
- no reviewer identity, OpenCode/Noema/Strix credential, NVIDIA NIM secret name, or scheduled-agent key scheme changes.
Standards basis
- Python 3.14 subprocess structured-argument, pipe, file-descriptor, timeout, and process-group semantics;
- CWE-770 resource allocation without limits or throttling;
- NIST SP 800-218 SSDF 1.1.
Stack after #764.
Outcome
Central sandbox verification remains usable and fail-closed when a repository command or E2E service emits excessive output. Parent memory and retained log files are capped before evidence redaction, while a bounded final diagnostic suffix remains available for review.
Problem
sandboxed_verify.pyandsandboxed_web_e2e.pycurrently usesubprocess.PIPE/communicate()-style capture for short-lived commands, which can buffer an unbounded stream in memory. Long-running E2E services write to ordinary files without a quota, andtail_text()reads the entire file before selecting the final lines. A malicious or defective repository process can therefore exhaust runner memory or disk before the redaction boundary executes.Scope
RLIMIT_FSIZE, because that limit would incorrectly constrain every regular file created by the child;shell=False, process-group cleanup, timeouts, exit status, output redaction, evidence notes, and environment scrubbing;CHANGELOG.md.Acceptance
Standards basis
Stack after #764.