← Back to PRs

#11961: fix: exec tool wraps shebang scripts in heredoc to use correct interpreter

by scott-memco open 2026-02-08 16:22 View on GitHub →
agents stale
## Summary Fixes #11724 - Exec tool cannot execute Python scripts with import statements. - **Root cause**: When multiline scripts with a shebang (e.g. `#!/usr/bin/env python3`) are passed to the exec tool, all execution paths (`sh -c`, `bash -c`, Docker `sh -lc`) treat the shebang as a comment and interpret subsequent lines as shell commands. This causes Python's `import os` to invoke ImageMagick's `import` binary. - **Fix**: Add `wrapScriptCommand()` in `node-shell.ts` that detects shebang-prefixed commands and wraps the script body in a single-quoted heredoc (`<<'EOF'`), so the shell delegates execution to the interpreter declared in the shebang line. - Applied across all four exec paths: sandbox (Docker), PTY, PTY fallback, regular spawn, and node-host (`buildNodeShellCommand`). ### Before ``` sh -c '#!/usr/bin/env python3 import os # <-- executed as ImageMagick "import" command print(os.getcwd()) # <-- shell error ' ``` ### After ``` sh -c '/usr/bin/env python3 <<'\''OPENCLAW_SCRIPT_EOF'\'' import os print(os.getcwd()) OPENCLAW_SCRIPT_EOF' ``` The heredoc uses a single-quoted marker to prevent shell variable expansion inside the script body. Non-shebang commands pass through unchanged. ## Test plan - [x] Added unit tests for `wrapScriptCommand()` covering Python, Ruby, Node.js shebangs, edge cases (empty body, no shebang, `\r\n` line endings, shebang-only, leading whitespace) - [x] Added integration test for `buildNodeShellCommand` with shebang-prefixed scripts - [x] Existing `buildNodeShellCommand` tests pass unchanged (regular commands are not affected) - [ ] Manual verification: run `exec` with a multiline Python script containing `import os` - [ ] Verify Docker sandbox path handles shebang scripts correctly Made with [Cursor](https://cursor.com) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes execution of multi-line shebang scripts (e.g. Python with `import`) by adding `wrapScriptCommand()` in `src/infra/node-shell.ts` and applying it across exec paths (local spawn/PTY, Docker sandbox, and node-host via `buildNodeShellCommand`). It wraps shebang-prefixed commands into a single-quoted heredoc so the declared interpreter receives the script body instead of `/bin/sh` interpreting subsequent lines as shell commands. Tests were added for `wrapScriptCommand()` and for `buildNodeShellCommand` behavior with a shebang script (`src/infra/node-shell.test.ts`). <h3>Confidence Score: 3/5</h3> - This PR is close to mergeable but has two correctness/safety issues in the new shebang-heredoc wrapping and approval/analysis consistency. - The core approach is sound and well-tested, but (1) a fixed heredoc marker can be prematurely terminated by script content, and (2) node exec allowlist/approval analysis is performed on the unwrapped command while execution uses the wrapped command, which can invalidate approvals/allowlist matching and produce misleading audit logs for shebang scripts. - src/infra/node-shell.ts, src/agents/bash-tools.exec.ts <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs