mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix(security): use temp file for GitHub token to avoid process listing exposure (#3301)
* fix(security): use temp file for GitHub token to avoid process listing exposure Fixes #3300 Agent: security-auditor Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(security): pass GitHub token via heredoc instead of local temp file The previous fix wrote the token to a temp file on the LOCAL host, but the command string was executed on the REMOTE server via runner.runServer(), so `cat` would fail with 'No such file or directory'. Switch to a heredoc which is parsed by the remote shell and never appears in /proc/*/cmdline. Agent: pr-maintainer Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(security): upload token to remote via SCP instead of heredoc The previous heredoc approach (`cat <<'EOF'`) doesn't work because all cloud runners wrap commands in `bash -c ${shellQuote(cmd)}`, and heredocs are not valid inside single-quoted bash -c strings. Use runner.uploadFile() (SCP) to place the token on the remote server as a temp file (mode 0600), then cat+rm it in the remote command. This is the same proven pattern used by uploadConfigFile(). The local temp file is always cleaned up after upload, and the remote temp file is cleaned up both on success (inline rm) and on failure (best-effort rm). Agent: security-auditor Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- 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
352c55c068
commit
fbf7aaa067
1 changed files with 21 additions and 2 deletions
|
|
@ -266,14 +266,33 @@ export async function offerGithubAuth(runner: CloudRunner, explicitlyRequested?:
|
||||||
}
|
}
|
||||||
|
|
||||||
let ghCmd = "curl --proto '=https' -fsSL https://openrouter.ai/labs/spawn/shared/github-auth.sh | bash";
|
let ghCmd = "curl --proto '=https' -fsSL https://openrouter.ai/labs/spawn/shared/github-auth.sh | bash";
|
||||||
|
// Upload the token to a remote temp file so it never appears in `ps auxe`
|
||||||
|
// process listings. We use runner.uploadFile() (SCP) — the same proven
|
||||||
|
// pattern as uploadConfigFile(). A heredoc won't work here because all
|
||||||
|
// cloud runners wrap commands in `bash -c ${shellQuote(cmd)}`, and
|
||||||
|
// heredocs are not valid inside single-quoted `bash -c '...'` strings.
|
||||||
|
let remoteTokenPath = "";
|
||||||
if (githubToken) {
|
if (githubToken) {
|
||||||
const tokenB64 = Buffer.from(githubToken).toString("base64");
|
const localTmpFile = join(getTmpDir(), `spawn_gh_token_${Date.now()}_${Math.random().toString(36).slice(2)}`);
|
||||||
ghCmd = `export GITHUB_TOKEN=$(printf '%s' ${shellQuote(tokenB64)} | base64 -d) && ${ghCmd}`;
|
remoteTokenPath = `/tmp/spawn_gh_token_${Date.now()}`;
|
||||||
|
writeFileSync(localTmpFile, githubToken, {
|
||||||
|
mode: 0o600,
|
||||||
|
});
|
||||||
|
const uploadResult = await asyncTryCatch(() => runner.uploadFile(localTmpFile, remoteTokenPath));
|
||||||
|
tryCatchIf(isOperationalError, () => unlinkSync(localTmpFile));
|
||||||
|
if (!uploadResult.ok) {
|
||||||
|
throw uploadResult.error;
|
||||||
|
}
|
||||||
|
ghCmd = `export GITHUB_TOKEN=$(cat ${shellQuote(remoteTokenPath)}) && rm -f ${shellQuote(remoteTokenPath)} && ${ghCmd}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
logStep("Installing and authenticating GitHub CLI on the remote server...");
|
logStep("Installing and authenticating GitHub CLI on the remote server...");
|
||||||
const ghSetup = await asyncTryCatchIf(isOperationalError, () => runner.runServer(ghCmd));
|
const ghSetup = await asyncTryCatchIf(isOperationalError, () => runner.runServer(ghCmd));
|
||||||
if (!ghSetup.ok) {
|
if (!ghSetup.ok) {
|
||||||
|
// Best-effort cleanup of remote token file if the command failed before rm ran
|
||||||
|
if (remoteTokenPath) {
|
||||||
|
await asyncTryCatchIf(isOperationalError, () => runner.runServer(`rm -f ${shellQuote(remoteTokenPath)}`));
|
||||||
|
}
|
||||||
logWarn("GitHub CLI setup failed (non-fatal, continuing)");
|
logWarn("GitHub CLI setup failed (non-fatal, continuing)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue