fix: prevent shell injection in AndroidExtEnv.execute_adb_with_cmd (CWE-78)#2026
Open
sebastiondev wants to merge 1 commit into
Open
Conversation
…WE-78) Use shlex.split() to tokenize the command string and pass it as a list to subprocess.run() with shell=False, preventing shell metacharacter injection via agent-controlled inputs (input_txt, ss_name, xml_name, etc.). Previously, user/agent-controlled strings were interpolated directly into a command string passed to subprocess.run(cmd, shell=True), allowing injection of arbitrary shell commands via metacharacters like ;, $(), |, &&.
This was referenced May 14, 2026
|
Closing this as inactive — no maintainer response after 14 days. The security finding and fix remain valid. If this is still relevant, I'm happy to reopen, rebase, or re-submit against a different branch. Just drop a comment. |
1 similar comment
|
Closing this as inactive — no maintainer response after 14 days. The security finding and fix remain valid. If this is still relevant, I'm happy to reopen, rebase, or re-submit against a different branch. Just drop a comment. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a shell command injection vulnerability (CWE-78) in
AndroidExtEnv.execute_adb_with_cmd. This method is the single chokepoint through which all 20+adbinvocations in the Android environment flow, and it currently runs an attacker-influenceable command string through the host shell.Vulnerability
metagpt/environment/android/android_ext_env.pyAndroidExtEnv.execute_adb_with_cmdThe vulnerable line:
adb_cmdis built via f-strings from agent-/LLM-supplied data throughout the file. For example, theuser_inputpath:The only sanitization on
input_txtstrips spaces and quotes — shell metacharacters such as;,&,|,`,$(), and newlines pass through untouched. An adversary that can influence the agent's task text (a realistic threat in multi-agent / tool-use deployments and any flow where task descriptions, page content, or tool outputs are fed back into the agent) can therefore execute arbitrary commands on the host.Fix
Tokenize the command with
shlex.splitand disable the shell:Rationale:
shlex.splitpreserves the existing quoting semantics callers already rely on (e.g.adb shell "am start ..."), so behavior for legitimate adb commands is unchanged.shell=Falseensures shell metacharacters in any embedded user/agent text remain literal arguments toadbrather than being interpreted by/bin/sh.The diff is intentionally minimal — one import and one call site:
Tests
Added
tests/security/test_cwe78_android_ext_env.pywith three regression checks (all passing locally):test_execute_adb_with_cmd_does_not_invoke_a_shell— AST-assertssubprocess.runis invoked withshell=False.test_execute_adb_with_cmd_passes_tokenized_argv— AST-asserts the first positional argument isshlex.split(adb_cmd)(not a raw string).test_agent_user_input_reaches_adb_execution_sink— Documents and pins the data-flow pathEnvAction.USER_INPUT → user_input → execute_adb_with_cmd, so future refactors can't silently re-introduce a shell-string sink without tripping the test.We also constructed a runtime PoC against the pre-fix code using a payload like
hello; touch /tmp/pwnedrouted throughuser_input; the file was created on the unpatched build and is no longer created after the patch.Security analysis
EnvAction.USER_INPUT.input_txtor another adb command builder) on a deployment that actually runs the Android environment withadbavailable. The existing input scrubbing only removes whitespace and quotes, which does not block command separators or substitutions.input_txtis now a malformedadb shell input textargument list thatadbrejects.Adversarial review
Before submitting we tried to disprove this. We checked whether the upstream
user_inputsanitizer or any wrapper neutralized shell metacharacters — it only strips spaces and quotes, leaving;,|,&,`,$(), and newlines intact. We considered whether the Android environment is gated behind operator-only configuration that would make agent input non-attacker-controlled — it isn't; in normal multi-agent/tool-use flows the LLM-produced text reaches this sink. We considered whethershell=Truewith a fixedadbprefix limits damage — it doesn't, because the shell evaluates the whole string and command separators escape theadbprefix entirely. The preconditions to exploit (LLM-influenced text + Android env enabled on a host withadb) do not already grant the attacker shell access on the operator's machine, so this fix provides genuine defense rather than restating an existing capability.cc @lewiswigmore