From d42b118fe3e8f06e3f7613a7c3f86fcef00480f8 Mon Sep 17 00:00:00 2001 From: Huanqi Cao Date: Sun, 5 Jul 2026 16:55:46 +0800 Subject: [PATCH] Spawn tsc by its JS entry so doc-typecheck runs on Windows execFileSync('node_modules/.bin/tsc') spawns an extensionless shim that is not executable on Windows (the CVE-2024-27980 class the sibling scripts hit); the catch treated the spawn failure as a compile failure with empty diagnostics. The .cmd shim would need shell:true, which concatenates args unescaped - a hazard for the temp project path - so invoke typescript/bin/tsc through the current node instead; identical behavior on every platform. Note this gate had never actually run on this Windows checkout: with the pre-eol=lf CRLF working copy the fence regex matched no ts blocks ('.' does not match \\r), so it reported 'no ts code blocks to check' and exited green. The LF working tree surfaced the spawn bug; with this fix the gate compiles all 21 blocks on Windows. (cherry picked from commit b49993c28e068c2beb411eae1f0c8ac4985aa3ae) --- scripts/doc-typecheck.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/doc-typecheck.ts b/scripts/doc-typecheck.ts index dfcbbf844c..86266f89b2 100644 --- a/scripts/doc-typecheck.ts +++ b/scripts/doc-typecheck.ts @@ -125,7 +125,12 @@ try { }) try { - execFileSync('node_modules/.bin/tsc', ['-b', join(tmp, 'tsconfig.json')], { cwd: root, stdio: 'pipe' }) + // tsc's JS entry via the current node, not the .bin shim: the extensionless + // shim is not spawnable on Windows (the CVE-2024-27980 class the sibling + // scripts hit), and the .cmd variant would need shell:true, which + // concatenates args UNESCAPED — a hazard for the temp project path. The JS + // entry behaves identically on every platform. + execFileSync(process.execPath, ['node_modules/typescript/bin/tsc', '-b', join(tmp, 'tsconfig.json')], { cwd: root, stdio: 'pipe' }) } catch (error: unknown) { const failed = error as { stdout?: Buffer; stderr?: Buffer } const out = `${failed.stdout?.toString() ?? ''}${failed.stderr?.toString() ?? ''}`