mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix(security): pipe install script via temp file instead of bash -c to prevent command injection (#3292)
Fixes #3291 Agent: security-auditor Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
439e5a1446
commit
ace5aa94d1
3 changed files with 24 additions and 13 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openrouter/spawn",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"spawn": "cli.js"
|
||||
|
|
|
|||
|
|
@ -313,9 +313,9 @@ describe("update-check", () => {
|
|||
expect(execFileSyncCalls[0].file).toBe("curl");
|
||||
expect(execFileSyncCalls[0].args).toContain("-fsSL");
|
||||
expect(execFileSyncCalls[0].args.some((a: string) => a.includes("install.sh"))).toBe(true);
|
||||
// 2. bash to execute fetched script
|
||||
// 2. bash to execute fetched script via temp file (not -c)
|
||||
expect(execFileSyncCalls[1].file).toBe("bash");
|
||||
expect(execFileSyncCalls[1].args[0]).toBe("-c");
|
||||
expect(execFileSyncCalls[1].args[0]).toMatch(/spawn-install-.*\.sh$/);
|
||||
// 3. which spawn for binary lookup
|
||||
expect(execFileSyncCalls[2].file).toBe("which");
|
||||
expect(execFileSyncCalls[2].args).toEqual([
|
||||
|
|
|
|||
|
|
@ -320,17 +320,28 @@ function performAutoUpdate(latestVersion: string, jsonOutput = false): void {
|
|||
throw psResult.error;
|
||||
}
|
||||
} else {
|
||||
// macOS/Linux: execute via bash -c
|
||||
executor.execFileSync(
|
||||
"bash",
|
||||
[
|
||||
"-c",
|
||||
scriptContent,
|
||||
],
|
||||
{
|
||||
stdio: installStdio,
|
||||
},
|
||||
// macOS/Linux: write to temp file and execute via bash to avoid
|
||||
// command injection and ARG_MAX limits (consistent with Windows path)
|
||||
const tmpFile = path.join(tmpdir(), `spawn-install-${Date.now()}.sh`);
|
||||
fs.writeFileSync(tmpFile, scriptContent, {
|
||||
mode: 0o700,
|
||||
});
|
||||
const bashResult = tryCatch(() =>
|
||||
executor.execFileSync(
|
||||
"bash",
|
||||
[
|
||||
tmpFile,
|
||||
],
|
||||
{
|
||||
stdio: installStdio,
|
||||
},
|
||||
),
|
||||
);
|
||||
// Best-effort cleanup of temp file
|
||||
tryCatchIf(isFileError, () => fs.unlinkSync(tmpFile));
|
||||
if (!bashResult.ok) {
|
||||
throw bashResult.error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue