Skip to content

fix(growth): security hardening — bun -e interpolation, pkill race, input validation#3294

Merged
louisgv merged 1 commit intoOpenRouterTeam:mainfrom
AhmedTMM:fix/growth-security-hardening
Apr 14, 2026
Merged

fix(growth): security hardening — bun -e interpolation, pkill race, input validation#3294
louisgv merged 1 commit intoOpenRouterTeam:mainfrom
AhmedTMM:fix/growth-security-hardening

Conversation

@AhmedTMM
Copy link
Copy Markdown
Collaborator

Summary

Batch security hardening for growth.sh and reddit-fetch.ts, resolving 9 real findings from the security scanner. Separately, I'll leave comments on 5 stale/hallucinated issues recommending they be closed, and 1 out-of-scope one (valibot refactor) for a follow-up PR.

growth.sh

reddit-fetch.ts

Closes

#3188, #3193, #3198, #3202, #3205, #3207, #3221, #3223, #3224

Not touched by this PR

Test plan

  • bash -n growth.sh — syntax clean
  • bunx biome check src/ — 0 errors on 184 files
  • bun test — 2043/2043 pass
  • Manual: next growth cycle runs cleanly on the VM (reviewer to verify after merge)

…nput validation

Closes a batch of real security findings filed against growth.sh and reddit-fetch.ts.

growth.sh:
- Switch all four `bun -e "...${VAR}..."` sites to env-var passing
  (_VAR="..." bun -e 'process.env._VAR'), per .claude/rules/shell-scripts.md.
  Closes OpenRouterTeam#3188, OpenRouterTeam#3221, OpenRouterTeam#3223.
- Spawn claude under `setsid` so it owns its own process group, and kill the
  group via `kill -SIG -PGID` instead of racing with pkill -P. Adds a numeric
  guard on CLAUDE_PID. Closes OpenRouterTeam#3193, OpenRouterTeam#3205.
- POST to SPA with Authorization header loaded from a 0600 temp config file
  (-K) and body from a 0600 temp file instead of here-string, so
  SPA_TRIGGER_SECRET never appears in ps/cmdline. Closes OpenRouterTeam#3224.
- Drop dead REDDIT_JSON=$(cat ...) line.
- Extend cleanup trap to also remove CLAUDE_OUTPUT_FILE, SPA_AUTH_FILE, SPA_BODY_FILE.

reddit-fetch.ts:
- Validate REDDIT_CLIENT_ID / REDDIT_CLIENT_SECRET don't contain ':' or CRLF
  (prevents Basic-auth corruption and header injection). Closes OpenRouterTeam#3198.
- Validate REDDIT_USERNAME against Reddit's charset before interpolating into
  the User-Agent header (prevents CRLF injection). Closes OpenRouterTeam#3207.
- Validate Reddit-API-returned author names against the same charset and
  encodeURIComponent them before interpolating into the /user/ API path
  (prevents path traversal from a hostile Reddit username). Closes OpenRouterTeam#3202.
Copy link
Copy Markdown
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: 80aca08

Findings

No security issues found. All changes are security hardening improvements:

growth.sh:

  • bun -e interpolation fixed (lines 68, 148-163, 180) — data passed via env vars per shell-scripts.md
  • ✅ Process group killing (lines 110, 124, 126) — atomic setsid + kill -PGID replaces race-prone pkill -P
  • ✅ CLAUDE_PID validation (lines 118-120) — guards against empty/non-numeric PID
  • ✅ SPA secret protection (lines 203-214) — passed via curl -K config file, never on command line
  • ✅ Temp file cleanup (line 37) — auth/body files added to cleanup trap

reddit-fetch.ts:

  • ✅ Credential validation (lines 26-28) — rejects : and newlines, prevents Basic-auth corruption and header injection
  • ✅ Username validation (lines 33-37) — CRLF injection prevention in User-Agent header
  • ✅ Author field sanitization (lines 222-223) — prevents path traversal, encodeURIComponent as defense-in-depth

Tests

  • bash -n: PASS
  • bun test: PASS (2104 pass, 0 fail)
  • curl|bash: N/A (no install script changes)
  • macOS compat: OK (uses env vars, no bash 4+ features)

-- security/pr-reviewer

@louisgv louisgv merged commit 2d7a23a into OpenRouterTeam:main Apr 14, 2026
6 checks passed
@AhmedTMM AhmedTMM deleted the fix/growth-security-hardening branch April 14, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment