Skip to content

security: constrain agent command execution - #4

Merged
harshitethic merged 7 commits into
mainfrom
security/safe-command-execution
Sep 8, 2026
Merged

harshitethic merged 7 commits into
mainfrom
security/safe-command-execution

Conversation

@harshitethic

@harshitethic harshitethic commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Problem

PatchPilot executed planner-supplied test commands and /api/execute input through bash -lc. The old endpoint blocklist caught only a few literal strings, leaving shell chaining, redirection, command substitution, and other arbitrary shell execution paths open.

A simple executable allowlist was not sufficient by itself: path-qualified binaries such as /tmp/pytest could impersonate an allowlisted tool, while generic command runners such as node -e, npm exec, pnpm exec, go run, and cargo run could still provide direct arbitrary-code escape hatches without using shell metacharacters.

Solution

  • parse one command into argv and execute it directly instead of invoking a shell
  • reject shell composition/redirection operators
  • reject path-qualified executables so allowlisted tool names resolve through PATH only
  • allow direct Python tooling only for pytest, ruff, mypy, and pyright
  • restrict python/python3 to -m pytest or -m unittest
  • restrict npm/pnpm/yarn to approved test, lint, typecheck, or check scripts and block exec
  • restrict Go to go test
  • restrict Cargo to test, check, or clippy
  • apply the policy to both model-generated test commands and /api/execute
  • add regressions for shell injection, path-qualified binaries, direct Node execution, package-manager exec escapes, go run, and cargo run

Scope / limitations

This removes the avoidable shell layer and closes obvious command-runner escape hatches. It is not a sandbox: approved test/lint tools and project-defined package scripts can still execute repository code. Strong isolation still requires a container/process sandbox and workspace/file-system controls.

Validation

The previous branch head passed Backend CI on Python 3.11 and 3.12. After the additional command-runner hardening commits, Backend CI is queued for the new head; no pass is claimed for those latest commits yet.

The connected workstation was offline during this work, so no local validation is claimed.

AI assistance disclosure: AI assistance was used to review the command-execution threat surface, identify bypass classes, prepare the focused hardening and regression tests, and inspect the resulting diff.

@harshitethic
harshitethic merged commit b8933bb into main Sep 8, 2026
2 checks passed
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