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)
This commit is contained in:
Huanqi Cao
2026-07-15 16:09:12 +08:00
committed by imccyu
parent 1c4bb7008d
commit d42b118fe3
+6 -1
View File
@@ -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() ?? ''}`