- Add printf %q command escaping to run_server/interactive_session in
Koyeb, Render, Railway, and GitHub Codespaces (matching pattern used
by E2B, Daytona, Northflank, Fly, and other providers)
- Use json_escape in exchange_oauth_code to prevent JSON injection via
crafted OAuth codes in shared/common.sh
- Use json_escape in Fly.io _fly_create_app to prevent JSON injection
via FLY_ORG env var, plus add validation for org slug format
- Pass Fly.io _fly_create_machine values via env vars instead of Python
string interpolation to prevent code injection
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace vulnerable heredoc patterns across 27 continue.sh scripts with
setup_continue_config() helper that uses json_escape() + upload_config_file()
to safely handle API keys containing special characters like quotes or braces.
Also fix _save_token_to_config() in shared/common.sh which had the same
unescaped heredoc vulnerability for local token storage.
Relates to #104
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Split _fly_create_and_start_machine (70 lines) into _fly_create_machine
and _fly_wait_for_machine_start for single-responsibility
- Replace ensure_koyeb_token (38 lines) with ensure_api_token_with_provider
- Replace ensure_railway_token (37 lines) with ensure_api_token_with_provider
- Remove _save_koyeb_token and _save_railway_token (handled by shared helper)
Net reduction: ~80 lines of duplicated code
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement railway/cline.sh following the standard Railway pattern:
- Install cline via npm
- Inject OPENAI_API_KEY and OPENAI_BASE_URL for OpenRouter compatibility
- Launch with 'cline' command
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement railway/amazonq.sh following the standard Railway pattern:
- Install Amazon Q CLI via AWS installer script
- Inject OPENAI_API_KEY and OPENAI_BASE_URL for OpenRouter compatibility
- Launch with 'q chat' command
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement railway/gemini.sh following the standard Railway pattern:
- Install @google/gemini-cli via npm
- Inject GEMINI_API_KEY, OPENAI_API_KEY, and OPENAI_BASE_URL
- Launch with OpenRouter compatibility
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Railway's inject_env_vars passed user-controlled values (e.g. OPENROUTER_API_KEY)
through bash -c without proper escaping, allowing shell injection. Replace with
the safe file-based pattern used by other providers (write to temp file, upload,
append to .bashrc).
Also add remote_path validation to Railway and Modal upload_file functions to
prevent single-quote breakout injection, matching the pattern already used by
Koyeb. Fix gptme.sh reference to non-existent inject_env_vars_railway function.
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix railway/gptme.sh calling nonexistent inject_env_vars_railway (should be inject_env_vars)
- Fix northflank claude/openclaw/aider using inject_env_vars_local (only writes .zshrc)
instead of inject_env_vars_northflank (writes both .bashrc and .zshrc)
- Update Railway README to list NanoClaw and gptme agents
- Update Northflank README to list all 8 implemented agents and add env var table
- Mark railway/gptme as implemented in manifest.json
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Railway: Missing base64 -w0 caused newline injection; unescaped remote_path
in single quotes allowed single-quote breakout command injection. Now uses
base64 -w0 with macOS fallback, printf '%q' for path escaping, and routes
through run_server instead of direct railway run bash -c.
Modal: Remote path was embedded in single quotes without escaping, allowing
single-quote breakout. Now uses printf '%q' for safe path escaping.
Koyeb: Used fragile deny-list validation for remote_path (rejecting specific
characters) and base64 without -w0 flag. Replaced with printf '%q' escaping
and added base64 -w0 with macOS fallback.
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
json_escape() returns a fully-quoted JSON string (e.g. "value") via
Python's json.dumps(). Callers using printf templates were wrapping
the result in additional quotes ("%s"), producing invalid JSON like
""value"". Remove the redundant quotes from all printf format strings
so json_escape's quotes are used directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add refactor.sh: Continuous service that spawns Claude Code agent teams
- Team roles: security-auditor, ux-engineer, complexity-hunter, test-engineer, issue-triager
- Focus on security, UX, complexity reduction, testing, and GitHub issue response
- Add GitHub issue template for bug reports (focused on error logs)
- Auto-triages and responds to issues within 1 hour
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>