Summary
When AutoAgent runs an agent it starts a Docker sandbox and, inside it, a small TCP server (autoagent/environment/tcp_server.py) that reads a command from any connecting client and executes it through /bin/bash -c via subprocess.Popen(..., shell=True). There is no authentication. The server binds 0.0.0.0 inside the container, and the container is created with docker run -p {communication_port}:{communication_port}, which Docker publishes on the host's 0.0.0.0, so the command server is reachable from the network. The container runs --user root and bind-mounts the host workspace directory (-v {local_workplace}:{docker_workplace}). Consequently any unauthenticated client that can reach the published port (default 12347/12346) executes arbitrary commands as root inside the container and can read and write the mounted host workspace.
Details
Container creation (autoagent/environment/docker_env.py):
docker_command = [
"docker", "run", "-d", "--name", self.container_name, "--user", "root",
"-v", f"{self.local_workplace}:{self.docker_workplace}", # host dir mounted into container
"-w", f"{self.docker_workplace}", "-p", f"{self.communication_port}:{self.communication_port}", BASE_IMAGES,
"/bin/bash", "-c",
f"python3 {self.docker_workplace}/tcp_server.py --workplace {self.workplace_name} --conda_path {self.conda_path} --port {self.communication_port}"
-p {port}:{port} with no host IP publishes the port on 0.0.0.0 of the host (the project's own check_container_ports documents the resulting mapping as 0.0.0.0:12345->12345/tcp). The command server (autoagent/environment/tcp_server.py) reads a command and runs it with a shell, with no authentication and no allowlist:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("0.0.0.0", args.port))
server.listen(1)
...
while True:
conn, addr = server.accept()
while True:
command = receive_all(conn) # raw bytes from the client
if not command:
break
modified_command = f"/bin/bash -c 'source {args.conda_path}/etc/profile.d/conda.sh && conda activate autogpt && cd /{args.workplace} && {command}'"
process = subprocess.Popen(modified_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
receive_all simply reads until a recv returns fewer than 4096 bytes, so one send of the command string is executed. The default --port is 12347 (autoagent/cli.py). There is no token, signature, or origin check; the protocol is "connect, send command, receive output." Because the container is --user root and mounts the host workspace, the executed command runs as root and can read/write the host-side workspace files (and pivot from there).
(There is a second, related exposure: autoagent/server.py runs a FastAPI "MetaChain API" with uvicorn.run(app, host="0.0.0.0", port=8000) and no authentication, dynamically exposing every tool and agent as an endpoint that runs the agent; if started, it is likewise an unauthenticated, network-exposed agent-execution API.)
POC: available upon request
Impact
Any unauthenticated attacker who can reach the published communication port (same LAN, shared/cloud network, or a co-located host) executes arbitrary commands as root inside the AutoAgent sandbox container and reads/writes the bind-mounted host workspace directory, with no credentials and no user interaction. This is remote code execution with a path to host data (the mounted workspace) and lateral movement. Fix: do not publish the command port on 0.0.0.0 (bind the container port to 127.0.0.1 only, e.g. -p 127.0.0.1:{port}:{port}, and have tcp_server.py bind 127.0.0.1); require an authentication token on the command channel; avoid running the container as root; and avoid shell=True. Apply the same (auth + loopback bind) to autoagent/server.py.
Summary
When AutoAgent runs an agent it starts a Docker sandbox and, inside it, a small TCP server (
autoagent/environment/tcp_server.py) that reads a command from any connecting client and executes it through/bin/bash -cviasubprocess.Popen(..., shell=True). There is no authentication. The server binds0.0.0.0inside the container, and the container is created withdocker run -p {communication_port}:{communication_port}, which Docker publishes on the host's0.0.0.0, so the command server is reachable from the network. The container runs--user rootand bind-mounts the host workspace directory (-v {local_workplace}:{docker_workplace}). Consequently any unauthenticated client that can reach the published port (default 12347/12346) executes arbitrary commands as root inside the container and can read and write the mounted host workspace.Details
Container creation (
autoagent/environment/docker_env.py):-p {port}:{port}with no host IP publishes the port on0.0.0.0of the host (the project's owncheck_container_portsdocuments the resulting mapping as0.0.0.0:12345->12345/tcp). The command server (autoagent/environment/tcp_server.py) reads a command and runs it with a shell, with no authentication and no allowlist:receive_allsimply reads until arecvreturns fewer than 4096 bytes, so onesendof the command string is executed. The default--portis 12347 (autoagent/cli.py). There is no token, signature, or origin check; the protocol is "connect, send command, receive output." Because the container is--user rootand mounts the host workspace, the executed command runs as root and can read/write the host-side workspace files (and pivot from there).(There is a second, related exposure:
autoagent/server.pyruns a FastAPI "MetaChain API" withuvicorn.run(app, host="0.0.0.0", port=8000)and no authentication, dynamically exposing every tool and agent as an endpoint that runs the agent; if started, it is likewise an unauthenticated, network-exposed agent-execution API.)POC: available upon request
Impact
Any unauthenticated attacker who can reach the published communication port (same LAN, shared/cloud network, or a co-located host) executes arbitrary commands as root inside the AutoAgent sandbox container and reads/writes the bind-mounted host workspace directory, with no credentials and no user interaction. This is remote code execution with a path to host data (the mounted workspace) and lateral movement. Fix: do not publish the command port on
0.0.0.0(bind the container port to127.0.0.1only, e.g.-p 127.0.0.1:{port}:{port}, and havetcp_server.pybind127.0.0.1); require an authentication token on the command channel; avoid running the container as root; and avoidshell=True. Apply the same (auth + loopback bind) toautoagent/server.py.