Skip to content

[Security] Unauthenticated Remote Code Execution (RCE) via Agent Bash Tool Bypass #2803

Description

@YLChen-007

Source: https://gist.github.com/YLChen-007/081bf68a2a02db2bdf5e4305ffb878e3/raw


Advisory Details

Title: Unauthenticated Remote Code Execution (RCE) via Agent Bash Tool Bypass

Description:

Summary

An unauthenticated Remote Code Execution (RCE) vulnerability exists in the agent module of chatgpt-on-wechat. The Bash tool is enabled and auto-loaded by default when the agent feature is used (which is the default configuration). The safety filter mechanism within the tool relies entirely on a trivial keyword blocklist (e.g., rm -rf /, shutdown), meaning it can be easily bypassed by slightly altered payloads or virtually any other command like file reads/writes, cron injection, or downloading malicious binaries. An attacker can execute arbitrary OS commands via the application's unauthenticated HTTP /message interface by prompting the LLM agent to invoke the Bash tool.

Details

The vulnerability stems from an insecure design where the default Bash tool directly executes shell commands without a sandbox, combined with an inadequate blocklist and unauthenticated access.

  1. Default Registration & Reachability: The agent/tools/__init__.py file automatically exports and loads the Bash tool by default ("agent": true is set in config-template.json). The web console (listening on port 9899) accepts unauthenticated POST requests on /message.
  2. Trivial Safety Filter: When the LLM decides to execute the bash tool based on a user's prompt, the input command is checked by the _get_safety_warning method in agent/tools/bash/bash.py. This method only checks for 10 exact-match patterns.
  3. Execution Sink: If the command doesn't match the exact 10 strings, it is passed without modification to a subprocess.run(command, shell=True) sink inside the execute method of Bash tool, running under whatever privileges the bot is running with (commonly root in Docker deployments).

PoC

Prerequisites

  • The chatgpt-on-wechat instance is deployed with default configurations (use_agent: true).
  • A valid LLM API key is configured (required for the bot to function and route tools).
  • The web channel interface is accessible (default port 9899).

Reproduction Steps

  1. Set up the target environment using the provided Docker Compose file:
    docker-compose.yml
    Run: docker compose up -d
    Note: Replace the placeholder OPENAI_API_KEY in memory or .env inside the container if needed to ensure the LLM can process messages.

  2. Verify Tool Behavior (Tool Level) inside the container using the PoC script:
    Download poc.py.
    Run: docker cp poc.py cow-bash-rce-test:/tmp/poc.py then docker exec cow-bash-rce-test python3 /tmp/poc.py.
    This verifies the safety filter bypasses internally.

  3. Verify the exploit externally (HTTP Level) using the HTTP Exploit script:
    Download exploit.py.
    Run: python3 exploit.py. This script sends crafted prompts to the /message endpoint, tricking the LLM into executing arbitrary code (e.g. cat /etc/shadow or creating backdoors).

  4. Run the Control Experiment to verify the blocklist behavior:
    Download control_tool_exec.py.
    Run it inside the container similarly to poc.py. This control script confirms that the trivial blocklist successfully stops EXACT-MATCH patterns, meaning the exploit is specifically bypassing this insufficient filter.

Log of Evidence

The complete trace of execution proving the vulnerability works alongside the control condition can be found here:
run.log

Impact

This is a Critical severity vulnerability.
An unauthenticated external attacker can gain complete Remote Code Execution on the system hosting chatgpt-on-wechat. Because applications are frequently deployed as Docker containers running as root, the attacker achieves complete host/container compromise, enabling lateral movement, data exfiltration, or hijacking of API keys.

Affected products

  • Ecosystem: python
  • Package name: chatgpt-on-wechat
  • Affected versions: <= 2.0.7
  • Patched versions:

Severity

  • Severity: Critical
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Weaknesses

  • CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

Occurrences

Permalink Description
https://github.com/zhayujie/chatgpt-on-wechat/blob/afd9471/agent/tools/bash/bash.py#L113-L118 The execution method where command input is passed directly to subprocess.run(shell=True).
https://github.com/zhayujie/chatgpt-on-wechat/blob/afd9471/agent/tools/bash/bash.py#L230-L245 The _get_safety_warning method which only uses a trivial array-based exact blocklist, failing to effectively sanitize inputs.
https://github.com/zhayujie/chatgpt-on-wechat/blob/afd9471/agent/tools/init.py Exposes Bash tool in the __all__ list, allowing default loading of the insecure tool when agent mode is enabled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions