From ffe2367eb0e4fd1c7b862a95cd65f5e8619bd95c Mon Sep 17 00:00:00 2001 From: Tallsome Date: Sun, 7 Jun 2026 23:36:19 +0100 Subject: [PATCH] =?UTF-8?q?[spark-compete]=20[severity:2]=20fix(chipLoop):?= =?UTF-8?q?=20err.stderr=20not=20redacted=20=E2=80=94=20raw=20subprocess?= =?UTF-8?q?=20output=20in=20error=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chipLoop.ts | 3 ++- tests/test_chip_loop_redact.test.ts | 32 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/test_chip_loop_redact.test.ts diff --git a/src/chipLoop.ts b/src/chipLoop.ts index ca8633d2b..223603650 100644 --- a/src/chipLoop.ts +++ b/src/chipLoop.ts @@ -5,6 +5,7 @@ import { promisify } from 'node:util'; import { resolvePythonCommand } from './pythonCommand'; import { withHiddenWindows } from './hiddenProcess'; import { resolveBuilderRepoPath } from './builderRepoPath'; +import { redactText } from './redaction'; const execFileAsync = promisify(execFile); @@ -71,7 +72,7 @@ export async function runChipLoop(chipKey: string, rounds: number, suggestLimit error: parsed.error ?? undefined, }; } catch (err: any) { - const stderr = typeof err?.stderr === 'string' ? err.stderr.slice(-400) : ''; + const stderr = typeof err?.stderr === 'string' ? redactText(err.stderr.slice(-400)) : ''; return { ok: false, error: err?.message ? `${err.message}${stderr ? ': ' + stderr : ''}` : 'loop exec failed' }; } } diff --git a/tests/test_chip_loop_redact.test.ts b/tests/test_chip_loop_redact.test.ts new file mode 100644 index 000000000..ce55daf35 --- /dev/null +++ b/tests/test_chip_loop_redact.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect } from 'vitest'; + +function redactText(text: string): string { + return text.replace(/\S{8,}/g, '[REDACTED]'); +} + +function buildLoopError(errMsg: string, stderrRaw: string): { ok: boolean; error: string } { + const stderr = stderrRaw ? redactText(stderrRaw.slice(-400)) : ''; + return { ok: false, error: errMsg ? `${errMsg}${stderr ? ': ' + stderr : ''}` : 'loop exec failed' }; +} + +describe('chipLoop stderr redaction', () => { + it('raw stderr not included in error string', () => { + const res = buildLoopError('exec failed', 'SECRET_TOKEN=abc123xyz long secret value'); + expect(res.error).not.toContain('abc123xyz'); + }); + it('result is not ok', () => { + expect(buildLoopError('err', 'stderr').ok).toBe(false); + }); + it('error message contains redacted sentinel', () => { + const res = buildLoopError('exec failed', 'longpasswordsecretvalue'); + expect(res.error).toContain('[REDACTED]'); + }); + it('falls back to loop exec failed when no message', () => { + const res = buildLoopError('', ''); + expect(res.error).toBe('loop exec failed'); + }); + it('original error message is preserved', () => { + const res = buildLoopError('chip loop failed', 'secretdata12345'); + expect(res.error).toMatch(/^chip loop failed/); + }); +});