fix(runtime): tolerate denied Node probe spawns (#150858)

This commit is contained in:
Dallin Romney 2026-09-17 07:29:38 -07:00 • committed by GitHub
parent 41784ac4c1
commit 7c3933ce17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 16 deletions

View file

@ -393,23 +393,23 @@ export function isUsableNode(nodePath, { allowCwd = false, trustedRoot, env = pr
probeEnv[key] = value;
}
}
const result = spawnSync(
resolved,
[
"-e",
`const probe = ${SQLITE_CAPABILITY_PROBE}; process.stdout.write(JSON.stringify({ version: process.versions.node, probe }));`,
],
{
encoding: "utf8",
env: probeEnv,
timeout: 5_000,
killSignal: "SIGKILL",
maxBuffer: 65_536,
windowsHide: true,
stdio: ["ignore", "pipe", "pipe"],
},
);
try {
const result = spawnSync(
resolved,
[
"-e",
`const probe = ${SQLITE_CAPABILITY_PROBE}; process.stdout.write(JSON.stringify({ version: process.versions.node, probe }));`,
],
{
encoding: "utf8",
env: probeEnv,
timeout: 5_000,
killSignal: "SIGKILL",
maxBuffer: 65_536,
windowsHide: true,
stdio: ["ignore", "pipe", "pipe"],
},
);
const details = JSON.parse(result.stdout);
return result.status === 0 && !nodeRuntimeFailure(details.version, details.probe);
} catch {

View file

@ -940,4 +940,18 @@ describe("candidate admission probe", () => {
expect(isUsableNode(candidate)).toBe(false);
});
});
it("rejects candidates when the permission model denies child processes", async () => {
await withRecoveryHome(async (home) => {
const candidate = await writeFixture(path.join(home, "bin/node"));
mocks.admissible.add(candidate);
mocks.probe.mockImplementation(() => {
throw Object.assign(new Error("Access to this API has been restricted"), {
code: "ERR_ACCESS_DENIED",
});
});
expect(isUsableNode(candidate)).toBe(false);
});
});
});