Uh oh!
There was an error while loading. Please reload this page.
fix: sanitize API key interpolation in run_server commands - #742
Conversation
Replace inline ${OPENROUTER_API_KEY} interpolation in run_server command
strings with inject_env_vars_ssh/inject_env_vars_local helpers that write
env vars to a temp file and upload it, avoiding shell metacharacter
interpretation of API keys on the remote server.
Affected files:
- latitude/continue.sh (inject_env_vars_ssh)
- scaleway/continue.sh (inject_env_vars_ssh)
- upcloud/continue.sh (inject_env_vars_ssh)
- kamatera/nanoclaw.sh (temp file upload for .env)
- daytona/continue.sh (inject_env_vars_local)
- e2b/continue.sh (inject_env_vars_local)
- modal/continue.sh (inject_env_vars_local)
- github-codespaces/continue.sh (inject_env_vars_local)
Fixes#736
Agent: security-auditor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
la14-1
left a comment
There was a problem hiding this comment.
Self-review by security-auditor:
All 8 files correctly migrated from inline API key interpolation to safe injection helpers.
Verification checklist:
- SSH-based clouds (latitude, scaleway, upcloud) correctly use
inject_env_vars_sshwith server IP as first arg - Non-SSH clouds (daytona, e2b, modal, github-codespaces) correctly use
inject_env_vars_localwithout server IP - kamatera/nanoclaw.sh
.envwrite uses temp file upload pattern (mktemp+chmod 600+upload_file+mv) to avoid shell interpolation bash -npasses on all 8 files- No test regressions (12 pre-existing failures on main, unchanged)
- The
inject_env_vars_*helpers usegenerate_env_config()which single-quotes values, preventing$(), backtick, and semicolon injection
Note on #737: The .gitignore already has .claude/skills/*/start-*.sh (the broad glob pattern). No change needed — the issue was resolved by a prior commit (8140c1b).
louisgv
left a comment
There was a problem hiding this comment.
Security Review
Verdict: APPROVED
Summary
This PR replaces inline shell interpolation of API keys in run_server commands with the safe inject_env_vars_ssh / inject_env_vars_local helper functions. These helpers write env vars to a temp file, upload it, and append to shell config on the remote side — avoiding shell command interpolation of secrets entirely. This is a clear security improvement.
The kamatera/nanoclaw.sh change additionally replaces a printf-based .env write via run_server with a local temp file + upload approach, which similarly avoids passing the API key through remote shell interpolation.
Findings
- No CRITICAL issues found
- No HIGH issues found
- No MEDIUM issues found
- [LOW] github-codespaces/continue.sh — the original code used
run_in_codespacebut the PR switches toinject_env_vars_local upload_file run_server. This is actually correct because the codespaces lib definesupload_file()andrun_server()wrappers that internally useCODESPACE_NAME, matching theinject_env_vars_localinterface. - [LOW] kamatera/nanoclaw.sh:44-49 — the temp file approach is good.
chmod 600andtrack_temp_fileensure proper permissions and cleanup. The uploaded file at/tmp/nanoclaw_envis immediately moved to~/nanoclaw/.env, minimizing exposure window.
Tests
- bash -n: PASS (all 8 files)
- bun test: N/A (no .ts files changed)
- curl|bash pattern: OK (source/eval fallback patterns unchanged)
- macOS compat: OK (no echo -e, no source <(), no ((var++)), no set -u, no local in subshells)
Notes
- This PR has merge conflicts (CONFLICTING status) and cannot be auto-merged. The author will need to resolve conflicts before merging.
- The security improvement is sound: moving from inline shell interpolation of API keys to file-based injection eliminates a class of command injection risks where special characters in API keys could break shell quoting.
Automated security review by spawn security team
louisgv
left a comment
There was a problem hiding this comment.
Security Review
Verdict: APPROVED
Summary
This PR correctly replaces unsafe inline ${OPENROUTER_API_KEY} interpolation in run_server command strings with the safe inject_env_vars_ssh / inject_env_vars_local helpers across 8 agent scripts. The core defense is generate_env_config() in shared/common.sh, which single-quotes values and escapes embedded single quotes using the standard '\'' pattern — this prevents shell injection from API keys containing $(cmd), backticks, semicolons, or other metacharacters.
Findings
- [LOW]
kamatera/nanoclaw.sh:47— The.envfile written viaprintf '%s'does not quote the value. If the API key contains characters that a.envparser might interpret (e.g.,#,\n), it could be misread. In practice, NanoClaw uses node.jsdotenvwhich handles this safely, and the value originates from OpenRouter OAuth which uses alphanumeric tokens. Risk is negligible. - [LOW]
kamatera/nanoclaw.sh:48-49— The uploaded temp file at/tmp/nanoclaw_envon the remote server may briefly have default (world-readable) permissions before beingmv'd. Since this is a freshly provisioned single-user server where the operator is root, this is not exploitable in practice.
No CRITICAL or HIGH issues found.
Tests
- bash -n: PASS (all 8 files)
- bun test: N/A (no test changes in this PR)
- curl|bash pattern: OK (all files use correct local-or-remote eval fallback)
- macOS compat: OK (no echo -e, source <(), ((var++)), set -u, or local-in-subshell)
Security Analysis
- Command injection: FIXED — the entire point of this PR. Inline
${OPENROUTER_API_KEY}in remote shell commands is replaced with temp-file-based injection that never passes the value through shell expansion. - Credential leaks: OK — temp files created with
chmod 600, tracked for cleanup viashred/rmon exit. - Unsafe patterns: None introduced. No
evalof user input, nosource <(). - generate_env_config: Correct single-quote escaping (
'→'\''). Values inside single quotes cannot be shell-expanded.
Note
This PR has merge conflicts (CONFLICTING status) that need resolution before merging.
Automated security review by spawn security team
louisgv
commented
Feb 12, 2026
Security review passed with APPROVED verdict (2 LOW findings, no CRITICAL/HIGH). This PR has merge conflicts that need to be resolved before merging. |
la14-1
commented
Feb 12, 2026
Closing this PR as all changes are already present on main. The security fixes for API key interpolation in these 8 scripts (daytona/continue.sh, e2b/continue.sh, github-codespaces/continue.sh, kamatera/nanoclaw.sh, latitude/continue.sh, modal/continue.sh, scaleway/continue.sh, upcloud/continue.sh) were applied through other PRs. Rebasing confirms zero diff against main. |
Fixes#736
Summary
${OPENROUTER_API_KEY}interpolation inrun_servercommand strings with safeinject_env_vars_ssh/inject_env_vars_localhelpers across 8 agent scriptschmod 600), upload it to the remote server, and source it — completely avoiding shell metacharacter interpretation of API key valueskamatera/nanoclaw.sh, the.envfile write also uses a temp file upload instead of inline interpolationWhy this matters
If an API key contained shell metacharacters (e.g.,
$(cmd), backticks,; cmd), the previous pattern would execute them on the remote server. Theinject_env_vars_*helpers fromshared/common.shalready handle this safely by single-quoting values ingenerate_env_config().Affected files
latitude/continue.shinject_env_vars_sshscaleway/continue.shinject_env_vars_sshupcloud/continue.shinject_env_vars_sshkamatera/nanoclaw.sh.envdaytona/continue.shinject_env_vars_locale2b/continue.shinject_env_vars_localmodal/continue.shinject_env_vars_localgithub-codespaces/continue.shinject_env_vars_localNote on #737
Issue #737 (.gitignore gap) is already resolved — the current
.gitignoreuses the broad pattern.claude/skills/*/start-*.shwhich covers all skill subdirectories.Test plan
bash -npasses on all 8 changed filesbun test— no regressions (12 pre-existing failures on main, unchanged)🤖 Generated with Claude Code