From bd621cc0239ec0f0e58f61b15972825519421a31 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 31 Aug 2026 22:19:16 +0000 Subject: [PATCH] =?UTF-8?q?fix(redact):=20large=20reports=20survive=20the?= =?UTF-8?q?=20pipe=20=E2=80=94=20exitCode=20instead=20of=20process.exit;?= =?UTF-8?q?=20inert=20test=20payload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wave's PR quality gate failed closed: gate-secret-scan.mjs pipes the diff's added lines into gstack-redact and parses the JSON report, but process.exit() discards stdout still buffered in the pipe — this wave's 646-finding report (202 KB) is the first big enough to arrive truncated (~145 KB) at node's collector, so JSON.parse failed and the gate read 'no report' as HIGH. The report and auto-redact body paths now set process.exitCode and let the runtime drain stdout; exit-code contract unchanged (verified 0/2/3 end-to-end). Also: the C1 test's stdin payload no longer uses a provider-prefix credential shape (the gate correctly flagged it; the content was never read on the error path under test). Co-Authored-By: Claude Fable 5 --- bin/gstack-redact | 11 +++++++++-- test/regression-pr1169-mktemp-fallbacks.test.ts | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/bin/gstack-redact b/bin/gstack-redact index 45bb1235f..fdf4e6363 100755 --- a/bin/gstack-redact +++ b/bin/gstack-redact @@ -307,7 +307,9 @@ function main() { "\n", ); } - process.exit(0); + // Same truncation class as the report path below: the redacted BODY can + // be arbitrarily large; let stdout drain instead of process.exit(0). + return; } const result = scan(input, opts); @@ -326,7 +328,12 @@ function main() { process.stdout.write(` HIGH=${HIGH} MEDIUM=${MEDIUM} LOW=${LOW} WARN=${WARN}\n`); } } - process.exit(code); + // process.exit() discards stdout still buffered in the pipe: a report past + // ~145 KB read by a slow consumer (node's gate-secret-scan.mjs collector) + // arrived truncated, JSON.parse failed, and the CI quality gate failed + // CLOSED on a clean scan. Set the exit code and let the runtime drain + // stdout instead — same contract, no truncation. + process.exitCode = code; } main(); diff --git a/test/regression-pr1169-mktemp-fallbacks.test.ts b/test/regression-pr1169-mktemp-fallbacks.test.ts index ea727705b..02cfd78f0 100644 --- a/test/regression-pr1169-mktemp-fallbacks.test.ts +++ b/test/regression-pr1169-mktemp-fallbacks.test.ts @@ -120,7 +120,7 @@ echo "SHOULD NOT REACH: $TMP_DIR"`; const r = spawnSync( "bun", [path.join(ROOT, "bin", "gstack-redact"), "--from-file", "", "--json"], - { encoding: "utf-8", input: "sk-ant-api03-not-really-a-key", timeout: 15_000 }, + { encoding: "utf-8", input: "placeholder stdin content (never read on the error path)", timeout: 15_000 }, ); expect(r.status).toBe(1); expect(r.stderr).toContain("non-empty path");