galaxyproject / galaxyproject/loom
Agent can hang a turn indefinitely on a runaway shell command (unbounded recursive grep over $HOME); no timeout, no visible cancel
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
## What happened
While debugging a Galaxy API 404, the agent (on `gemini-3.5-flash`) issued this via the `bash` tool:
```
grep -rn "galaxy_run_user_tool" /Users/anton/ 2>/dev/null
```
A **recursive grep of the entire home directory** — scanning `node_modules`, `Library`, caches, everything. It ran for **~7 minutes at 50–80% CPU** and never returned; the agent sat mid-turn with **no `tool_execution_end`**, looking frozen. It only resolved when the process was killed manually (`kill `).
From the run log: the turn `message_end` emitted a `bash` toolCall, `tool_execution_start` fired at 12:20:13, the last `tool_execution_update` was 12:20:18, and then nothing — the turn was blocked on the subprocess.
## Why it's bad
- **No wall-clock bound on shell commands** — a single command can stall a turn indefinitely. The UI just shows "thinking"/running with no indication a subprocess is the bottleneck.
- **No scoping guardrail** — recursing over `/Users/anton/` (or `/`) is almost never intended; the agent meant to search the repo/cwd. `grep -rn` over `$HOME` is pathological (huge, slow, noisy).
- **No user-visible cancel for the specific command.** Orbit already has a proc-monitor (`app/src/main/proc-monitor.ts`) surfacing per-subprocess CPU/mem/runtime in the Activity tab, but there's no "kill this command" affordance — the only recovery was killing the PID from a terminal or quitting the app.
- The exec-guard allowed it (it's a read-only grep), so it wasn't gated.
## Proposed handling
1. **Wall-clock timeout on the bash tool.** Default cap (e.g. 60–120s, configurable); on timeout, kill the process group and return a clear `tool_result` ("command exceeded Ns and was terminated") so the turn **continues** instead of hanging. This is the highest-leverage fix.
2. **Surface + cancel long-running commands in the UI.** The proc-monitor already tracks runtime — when a subprocess exceeds a threshold, show it prominently in the Activity tab with a **Stop** button wired to kill its process group. (Pairs naturally with the existing proc-monitor.)
3. **Exec-guard heuristic for broad recursive searches.** Flag/ask (or warn) on commands that recurse over very broad roots — `/`, `$HOME`, `/Users`, `~` — or lack ignore/exclude args, similar to other risky-op gating. At minimum, log a hint.
4. **Steer the agent toward scoped, fast search.** System-prompt/tool guidance: prefer the cwd/repo and an ignore-aware searcher (the repo already uses `ugrep`/ripgrep-style search elsewhere) over raw `grep -rn` across the home dir. Bias default search root to the analysis dir.
5. **Output cap** (secondary): even when such a command does return, cap the captured output so a giant result set doesn't flood context.
## Acceptance criteria
- [ ] A shell command that exceeds the timeout is killed and the turn proceeds with a clear timeout result (no indefinite hang).
- [ ] A long-running subprocess is visible in the Activity tab with a working Stop control.
- [ ] Broad recursive searches over `$HOME`/`/` are either prevented, gated, or steered to a scoped root.
## Related
- `app/src/main/proc-monitor.ts` (existing per-subprocess monitoring to build the cancel UI on)
- exec-guard (local-execution safety gate) — natural home for the broad-search heuristic
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.