From 74c215bceafa1ef64e82a648923c52a80a87a9e9 Mon Sep 17 00:00:00 2001 From: Thierno Bah <44367278+soulbah@users.noreply.github.com> Date: Thu, 8 Oct 2026 23:25:39 +0200 Subject: [PATCH] fix(distribution): verify quoted native input paths --- scripts/verify-platform-runtime.test.ts | 11 +++++++++++ scripts/verify-platform-runtime.ts | 12 +++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scripts/verify-platform-runtime.test.ts b/scripts/verify-platform-runtime.test.ts index ea4f699..1d7ca10 100644 --- a/scripts/verify-platform-runtime.test.ts +++ b/scripts/verify-platform-runtime.test.ts @@ -187,6 +187,17 @@ test("redact replaces known paths without touching unrelated text", () => { ); }); +test("redact covers raw and quoted Windows paths while preserving diagnostic filenames", () => { + const sandbox = String.raw`R:\fixture\sandbox`; + const input = `${sandbox}\\outputs\\missing input.json`; + const redactions = [{ path: sandbox, placeholder: "" }]; + expect(redact(`reading ${input}`, redactions)).toBe( + String.raw`reading \outputs\missing input.json`, + ); + const headline = redact(`cannot read ${JSON.stringify(input)}`, redactions); + expect(headline).toBe(String.raw`cannot read "\\outputs\\missing input.json"`); +}); + test("runBinary executes a local executable and reports failures", () => { if (process.platform === "win32") return; const sandbox = mkdtempSync(join(tmpdir(), "rootform-run-")); diff --git a/scripts/verify-platform-runtime.ts b/scripts/verify-platform-runtime.ts index 4c1a899..9e2b148 100644 --- a/scripts/verify-platform-runtime.ts +++ b/scripts/verify-platform-runtime.ts @@ -164,7 +164,10 @@ export function childEnvironment( export function redact(text: string, redactions: readonly Redaction[]): string { let result = text; for (const entry of [...redactions].sort((left, right) => right.path.length - left.path.length)) { - result = result.replaceAll(entry.path, entry.placeholder); + const quotedPath = JSON.stringify(entry.path).slice(1, -1); + result = result + .replaceAll(quotedPath, entry.placeholder) + .replaceAll(entry.path, entry.placeholder); } return result; } @@ -1315,7 +1318,7 @@ export async function runJourney( assertCommandRefusal(checkInput(missingInput, "runtime-proofs.policy.passes"), { code: "INPUT_UNREADABLE", exitCode: 4, - headline: 'cannot read "/outputs/missing input.json"', + headline: redact(`cannot read ${JSON.stringify(missingInput)}`, redactions), }), ); inputRefusals.oversized = attempt("oversized-input-refused-before-compilation", () => { @@ -1323,7 +1326,10 @@ export async function runJourney( const refusal = assertCommandRefusal(outcome, { code: "INPUT_REFUSED", exitCode: 3, - headline: 'input "/outputs/oversized.json" exceeds the 128 MiB limit', + headline: redact( + `input ${JSON.stringify(oversizedInput)} exceeds the 128 MiB limit`, + redactions, + ), }); if (outcome.stderr.includes("Compiling")) { throw new Error("oversized input reached compilation");