mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix(security): guarantee temp file cleanup in performAutoUpdate (#3307)
Restructure temp file write-execute-cleanup in performAutoUpdate so cleanup is unconditionally reached after tryCatch captures any exec error. Previously, the Windows and Unix paths each had separate tryCatch+cleanup+rethrow sequences that could diverge under future edits. Now a single tryCatch wraps the platform-branching exec, with cleanup always running before any error is re-thrown. Fixes #3306 Agent: security-auditor Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1e64d34e5a
commit
d1d51fb06d
2 changed files with 28 additions and 27 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openrouter/spawn",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.12",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"spawn": "cli.js"
|
||||
|
|
|
|||
|
|
@ -332,11 +332,22 @@ function performAutoUpdate(latestVersion: string, jsonOutput = false): void {
|
|||
const platform = isWindows() ? "windows" : "unix";
|
||||
validateInstallScript(scriptContent, platform);
|
||||
|
||||
if (isWindows()) {
|
||||
// Windows: write to temp file and execute via PowerShell
|
||||
const tmpFile = path.join(tmpdir(), `spawn-install-${Date.now()}.ps1`);
|
||||
fs.writeFileSync(tmpFile, scriptContent);
|
||||
const psResult = tryCatch(() =>
|
||||
// Write install script to temp file, execute, and guarantee cleanup.
|
||||
// Uses tryCatch so cleanup always runs before any error is re-thrown.
|
||||
const tmpExt = isWindows() ? "ps1" : "sh";
|
||||
const tmpFile = path.join(tmpdir(), `spawn-install-${Date.now()}.${tmpExt}`);
|
||||
fs.writeFileSync(
|
||||
tmpFile,
|
||||
scriptContent,
|
||||
isWindows()
|
||||
? undefined
|
||||
: {
|
||||
mode: 0o700,
|
||||
},
|
||||
);
|
||||
|
||||
const execResult = tryCatch(() => {
|
||||
if (isWindows()) {
|
||||
executor.execFileSync(
|
||||
"powershell.exe",
|
||||
[
|
||||
|
|
@ -348,21 +359,8 @@ function performAutoUpdate(latestVersion: string, jsonOutput = false): void {
|
|||
{
|
||||
stdio: installStdio,
|
||||
},
|
||||
),
|
||||
);
|
||||
// Best-effort cleanup of temp file
|
||||
tryCatchIf(isFileError, () => fs.unlinkSync(tmpFile));
|
||||
if (!psResult.ok) {
|
||||
throw psResult.error;
|
||||
}
|
||||
} else {
|
||||
// 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(() =>
|
||||
);
|
||||
} else {
|
||||
executor.execFileSync(
|
||||
"bash",
|
||||
[
|
||||
|
|
@ -371,13 +369,16 @@ function performAutoUpdate(latestVersion: string, jsonOutput = false): void {
|
|||
{
|
||||
stdio: installStdio,
|
||||
},
|
||||
),
|
||||
);
|
||||
// Best-effort cleanup of temp file
|
||||
tryCatchIf(isFileError, () => fs.unlinkSync(tmpFile));
|
||||
if (!bashResult.ok) {
|
||||
throw bashResult.error;
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Cleanup runs unconditionally — tryCatch above captures any exec error
|
||||
// without short-circuiting, so we always reach this line.
|
||||
tryCatchIf(isFileError, () => fs.unlinkSync(tmpFile));
|
||||
|
||||
if (!execResult.ok) {
|
||||
throw execResult.error;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue