Skip to content

fix: [#376] Prevent command injection in TextEditorTool._view()#386

Open
nandanosql wants to merge 1 commit into
bytedance:mainfrom
nandanosql:fix/issue-376-command-injection
Open

fix: [#376] Prevent command injection in TextEditorTool._view()#386
nandanosql wants to merge 1 commit into
bytedance:mainfrom
nandanosql:fix/issue-376-command-injection

Conversation

@nandanosql
Copy link
Copy Markdown

Fixes #376

Problem

The _view() method in TextEditorTool interpolated the user-supplied path directly into a shell command string passed to create_subprocess_shell. A directory name containing shell metacharacters (e.g. ; rm -rf /, $(malicious_command)) could execute arbitrary commands.

Solution

Replaced the shell-based find invocation with asyncio.create_subprocess_exec using a list of arguments. This bypasses the shell entirely, so metacharacters in path names are treated as literal characters by find(1).

Changes

  • In _view(): replaced await run(rf"find {path} ...") with await asyncio.create_subprocess_exec("find", str(path), ...)
  • The path is now passed as a separate argument, preventing shell interpretation

The _view() method was using shell interpolation (create_subprocess_shell)
to run .
./.git
./.git/COMMIT_EDITMSG
./.git/FETCH_HEAD
./.git/HEAD
./.git/branches
./.git/config
./.git/description
./.git/hooks
./.git/hooks/applypatch-msg.sample
./.git/hooks/commit-msg.sample
./.git/hooks/fsmonitor-watchman.sample
./.git/hooks/post-update.sample
./.git/hooks/pre-applypatch.sample
./.git/hooks/pre-commit.sample
./.git/hooks/pre-merge-commit.sample
./.git/hooks/pre-push.sample
./.git/hooks/pre-rebase.sample
./.git/hooks/pre-receive.sample
./.git/hooks/prepare-commit-msg.sample
./.git/hooks/push-to-checkout.sample
./.git/hooks/sendemail-validate.sample
./.git/hooks/update.sample
./.git/index
./.git/info
./.git/info/exclude
./.git/logs
./.git/logs/HEAD
./.git/logs/refs
./.git/logs/refs/heads
./.git/logs/refs/heads/fix
./.git/logs/refs/heads/fix/issue-357-deduplicate-tool-calls
./.git/logs/refs/heads/fix/issue-376-command-injection
./.git/logs/refs/heads/main
./.git/logs/refs/remotes
./.git/logs/refs/remotes/origin
./.git/logs/refs/remotes/origin/HEAD
./.git/logs/refs/remotes/upstream
./.git/logs/refs/remotes/upstream/chao-peng-patch-1
./.git/logs/refs/remotes/upstream/chao-peng-patch-2
./.git/logs/refs/remotes/upstream/dev
./.git/logs/refs/remotes/upstream/dev/ckg_multi_language
./.git/logs/refs/remotes/upstream/dev/fix_indefinite_cli_loop
./.git/logs/refs/remotes/upstream/dev/llm_client_refactor
./.git/logs/refs/remotes/upstream/dev/refactor_traj
./.git/logs/refs/remotes/upstream/dev/rust
./.git/logs/refs/remotes/upstream/dev/rust_agent_fix
./.git/logs/refs/remotes/upstream/dev/rust_app
./.git/logs/refs/remotes/upstream/dev/rust_config
./.git/logs/refs/remotes/upstream/dev/rust_llm_basics
./.git/logs/refs/remotes/upstream/dev/rust_llm_clients
./.git/logs/refs/remotes/upstream/dev/rust_tools
./.git/logs/refs/remotes/upstream/dev/technical_report
./.git/logs/refs/remotes/upstream/dev/update_mcp_support
./.git/logs/refs/remotes/upstream/dev/update_readme
./.git/logs/refs/remotes/upstream/dev/yaml_config
./.git/logs/refs/remotes/upstream/feat
./.git/logs/refs/remotes/upstream/feat/new_cli
./.git/logs/refs/remotes/upstream/feat/patch_selection
./.git/logs/refs/remotes/upstream/feat/selector_agent
./.git/logs/refs/remotes/upstream/feat/update_readme
./.git/logs/refs/remotes/upstream/hotfix
./.git/logs/refs/remotes/upstream/hotfix/remove_debug_print
./.git/logs/refs/remotes/upstream/hotfix/working_dir_bug
./.git/logs/refs/remotes/upstream/main
./.git/objects
./.git/objects/13
./.git/objects/13/f607c4e90665ca62e7e06a04f00898a263f652
./.git/objects/2e
./.git/objects/2e/a2fb66fa1ad8fa3ba606c077fafece8e38a6a2
./.git/objects/49
./.git/objects/49/9d1dde12d4b5d7e9de0d8f56a76973f2696879
./.git/objects/7b
./.git/objects/7b/51248994595778b4874122e80a66c72cf3fba6
./.git/objects/b6
./.git/objects/b6/2ed75120caae1d9ca3f4ca9e609336abeb2f54
./.git/objects/e8
./.git/objects/e8/a5661778d4aca34ac831219499254dc915362e
./.git/objects/info
./.git/objects/pack
./.git/objects/pack/pack-0742edc1b2e72d71fe7cf10c663d6528539bd8a1.idx
./.git/objects/pack/pack-0742edc1b2e72d71fe7cf10c663d6528539bd8a1.pack
./.git/objects/pack/pack-0742edc1b2e72d71fe7cf10c663d6528539bd8a1.rev
./.git/objects/pack/pack-60170791723b06f21b5c0ba137f8ca4fe3574564.idx
./.git/objects/pack/pack-60170791723b06f21b5c0ba137f8ca4fe3574564.pack
./.git/objects/pack/pack-60170791723b06f21b5c0ba137f8ca4fe3574564.rev
./.git/packed-refs
./.git/refs
./.git/refs/heads
./.git/refs/heads/fix
./.git/refs/heads/fix/issue-357-deduplicate-tool-calls
./.git/refs/heads/fix/issue-376-command-injection
./.git/refs/heads/main
./.git/refs/remotes
./.git/refs/remotes/origin
./.git/refs/remotes/origin/HEAD
./.git/refs/remotes/upstream
./.git/refs/remotes/upstream/chao-peng-patch-1
./.git/refs/remotes/upstream/chao-peng-patch-2
./.git/refs/remotes/upstream/dev
./.git/refs/remotes/upstream/dev/ckg_multi_language
./.git/refs/remotes/upstream/dev/fix_indefinite_cli_loop
./.git/refs/remotes/upstream/dev/llm_client_refactor
./.git/refs/remotes/upstream/dev/refactor_traj
./.git/refs/remotes/upstream/dev/rust
./.git/refs/remotes/upstream/dev/rust_agent_fix
./.git/refs/remotes/upstream/dev/rust_app
./.git/refs/remotes/upstream/dev/rust_config
./.git/refs/remotes/upstream/dev/rust_llm_basics
./.git/refs/remotes/upstream/dev/rust_llm_clients
./.git/refs/remotes/upstream/dev/rust_tools
./.git/refs/remotes/upstream/dev/technical_report
./.git/refs/remotes/upstream/dev/update_mcp_support
./.git/refs/remotes/upstream/dev/update_readme
./.git/refs/remotes/upstream/dev/yaml_config
./.git/refs/remotes/upstream/feat
./.git/refs/remotes/upstream/feat/new_cli
./.git/refs/remotes/upstream/feat/patch_selection
./.git/refs/remotes/upstream/feat/selector_agent
./.git/refs/remotes/upstream/feat/update_readme
./.git/refs/remotes/upstream/hotfix
./.git/refs/remotes/upstream/hotfix/remove_debug_print
./.git/refs/remotes/upstream/hotfix/working_dir_bug
./.git/refs/remotes/upstream/main
./.git/refs/tags
./.git/shallow
./.github
./.github/ISSUE_TEMPLATE
./.github/ISSUE_TEMPLATE/bug-report.yml
./.github/ISSUE_TEMPLATE/config.yml
./.github/ISSUE_TEMPLATE/feature-request.yml
./.github/ISSUE_TEMPLATE/proposal.yml
./.github/ISSUE_TEMPLATE/question.yml
./.github/pull_request_template.md
./.github/workflows
./.github/workflows/pre-commit.yml
./.github/workflows/unit-test.yml
./.gitignore
./.pre-commit-config.yaml
./.python-version
./.vscode
./.vscode/launch.template.json
./CONTRIBUTING.md
./LICENSE
./Makefile
./README.md
./docs
./docs/TRAJECTORY_RECORDING.md
./docs/legacy_config.md
./docs/roadmap.md
./docs/tools.md
./evaluation
./evaluation/README.md
./evaluation/__init__.py
./evaluation/patch_selection
./evaluation/patch_selection/README.md
./evaluation/patch_selection/analysis.py
./evaluation/patch_selection/example
./evaluation/patch_selection/example/example.jsonl
./evaluation/patch_selection/selector.py
./evaluation/patch_selection/trae_selector
./evaluation/patch_selection/trae_selector/__init__.py
./evaluation/patch_selection/trae_selector/sandbox.py
./evaluation/patch_selection/trae_selector/selector_agent.py
./evaluation/patch_selection/trae_selector/selector_evaluation.py
./evaluation/patch_selection/trae_selector/tools
./evaluation/patch_selection/trae_selector/tools/tools
./evaluation/patch_selection/trae_selector/tools/tools/base.py
./evaluation/patch_selection/trae_selector/tools/tools/bash.py
./evaluation/patch_selection/trae_selector/tools/tools/edit.py
./evaluation/patch_selection/trae_selector/tools/tools/execute_bash.py
./evaluation/patch_selection/trae_selector/tools/tools/execute_str_replace_editor.py
./evaluation/patch_selection/trae_selector/tools/tools/run.py
./evaluation/patch_selection/trae_selector/utils.py
./evaluation/run_evaluation.py
./evaluation/setup.sh
./evaluation/utils.py
./pyproject.toml
./server
./server/Readme.md
./tests
./tests/agent
./tests/agent/test_trae_agent.py
./tests/test_cli.py
./tests/tools
./tests/tools/test_bash_tool.py
./tests/tools/test_edit_tool.py
./tests/tools/test_json_edit_tool.py
./tests/tools/test_mcp_tool.py
./tests/utils
./tests/utils/test_config.py
./tests/utils/test_google_client.py
./tests/utils/test_mcp_client.py
./tests/utils/test_ollama_client_utils.py
./tests/utils/test_openrouter_client_utils.py
./trae_agent
./trae_agent/__init__.py
./trae_agent/agent
./trae_agent/agent/__init__.py
./trae_agent/agent/agent.py
./trae_agent/agent/agent_basics.py
./trae_agent/agent/base_agent.py
./trae_agent/agent/docker_manager.py
./trae_agent/agent/trae_agent.py
./trae_agent/cli.py
./trae_agent/dist
./trae_agent/dist/dist_tools
./trae_agent/dist/dist_tools/edit_tool
./trae_agent/dist/dist_tools/json_edit_tool
./trae_agent/prompt
./trae_agent/prompt/__init__.py
./trae_agent/prompt/agent_prompt.py
./trae_agent/tools
./trae_agent/tools/__init__.py
./trae_agent/tools/base.py
./trae_agent/tools/bash_tool.py
./trae_agent/tools/ckg
./trae_agent/tools/ckg/base.py
./trae_agent/tools/ckg/ckg_database.py
./trae_agent/tools/ckg_tool.py
./trae_agent/tools/docker_tool_executor.py
./trae_agent/tools/edit_tool.py
./trae_agent/tools/edit_tool_cli.py
./trae_agent/tools/json_edit_tool.py
./trae_agent/tools/json_edit_tool_cli.py
./trae_agent/tools/mcp_tool.py
./trae_agent/tools/run.py
./trae_agent/tools/sequential_thinking_tool.py
./trae_agent/tools/task_done_tool.py
./trae_agent/utils
./trae_agent/utils/cli
./trae_agent/utils/cli/__init__.py
./trae_agent/utils/cli/cli_console.py
./trae_agent/utils/cli/console_factory.py
./trae_agent/utils/cli/rich_console.py
./trae_agent/utils/cli/rich_console.tcss
./trae_agent/utils/cli/simple_console.py
./trae_agent/utils/config.py
./trae_agent/utils/constants.py
./trae_agent/utils/lake_view.py
./trae_agent/utils/legacy_config.py
./trae_agent/utils/llm_clients
./trae_agent/utils/llm_clients/anthropic_client.py
./trae_agent/utils/llm_clients/azure_client.py
./trae_agent/utils/llm_clients/base_client.py
./trae_agent/utils/llm_clients/doubao_client.py
./trae_agent/utils/llm_clients/google_client.py
./trae_agent/utils/llm_clients/llm_basics.py
./trae_agent/utils/llm_clients/llm_client.py
./trae_agent/utils/llm_clients/ollama_client.py
./trae_agent/utils/llm_clients/openai_client.py
./trae_agent/utils/llm_clients/openai_compatible_base.py
./trae_agent/utils/llm_clients/openrouter_client.py
./trae_agent/utils/llm_clients/readme.md
./trae_agent/utils/llm_clients/retry_utils.py
./trae_agent/utils/mcp_client.py
./trae_agent/utils/trajectory_recorder.py
./trae_config.json.example
./trae_config.yaml.example
./uv.lock with user-supplied path, allowing shell metacharacters in
directory names to inject arbitrary commands.

Replace shell=True execution with asyncio.create_subprocess_exec using
list arguments, which avoids shell interpretation entirely. The path is
passed as a separate argument to find(1) so special characters in
directory names are handled safely.
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

[Security] Command Injection in TextEditorTool._view() via malicious directory names

2 participants