Skip to content

fix(init): run commands without shell to eliminate injection surface#665

Merged
betegon merged 1 commit intomainfrom
fix/init-no-shell-spawn
Apr 6, 2026
Merged

fix(init): run commands without shell to eliminate injection surface#665
betegon merged 1 commit intomainfrom
fix/init-no-shell-spawn

Conversation

@betegon
Copy link
Copy Markdown
Member

@betegon betegon commented Apr 6, 2026

Summary

  • Replace spawn({ shell: true }) with direct executable invocation — command strings are split into [executable, ...args] and passed to spawn without a shell
  • Eliminates shell injection as an attack vector entirely: metacharacters become harmless literal arguments when no shell interprets them
  • The existing validateCommand() blocklist (metachar, env var, blocked executable checks) is retained as defense-in-depth

Addresses this review comment.

Test plan

  • Updated tests to use /bin/echo and /usr/bin/false instead of shell builtins
  • All existing run-commands tests pass (stdout capture, error handling, blocked commands, dry-run, batch validation)
  • tsc --noEmit passes
  • biome check passes

🤖 Generated with Claude Code

Replace spawn({ shell: true }) with direct executable invocation by
splitting the command string into [executable, ...args]. This eliminates
shell injection as an attack vector entirely — metacharacters become
harmless literal arguments. The existing validateCommand() blocklist is
retained as defense-in-depth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Bug Fixes 🐛

Init

  • Run commands without shell to eliminate injection surface by betegon in #665
  • Use opendir for listDir and validate symlinks during traversal by betegon in #663
  • Rename 'Custom Metrics' feature label to 'Metrics' by MathurAditya724 in #659
  • Add reactFeatures to feature display info by MathurAditya724 in #658
  • Generate spinner messages from payload params instead of server detail by MathurAditya724 in #655

Other

  • (errors) Separate informational notes from actionable alternatives in ContextError by BYK in #651
  • Fix set-commits --auto, document release workflow pitfalls by BYK in #650

Internal Changes 🔧

  • (init) Use mdKvTable and renderMarkdown for wizard summary by betegon in #661
  • Regenerate skill files and command docs by github-actions[bot] in eb1b19e7

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Codecov Results 📊

134 passed | Total: 134 | Pass Rate: 100% | Execution Time: 0ms

📊 Comparison with Base Branch

Metric Change
Total Tests
Passed Tests
Failed Tests
Skipped Tests

✨ No test changes detected

All tests are passing successfully.

✅ Patch coverage is 100.00%. Project has 1428 uncovered lines.
✅ Project coverage is 95.54%. Comparing base (base) to head (head).

Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    95.53%    95.54%    +0.01%
==========================================
  Files          220       220         —
  Lines        31986     31986         —
  Branches         0         0         —
==========================================
+ Hits         30555     30558        +3
- Misses        1431      1428        -3
- Partials         0         0         —

Generated by Codecov Action

@betegon betegon merged commit 04a1efd into main Apr 6, 2026
24 checks passed
@betegon betegon deleted the fix/init-no-shell-spawn branch April 6, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant