CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-61492
10.00.68%

The Robot Has a Gun: Breaking terminal-controller-mcp via Shell Gymnastics

Alon Barad
Alon Barad
Software Engineer

Feb 23, 2026·5 min read·13 visits

PoC Available

Executive Summary (TL;DR)

The terminal-controller-mcp package, designed to give AI models terminal access, attempted to block dangerous commands like 'mkfs' using a simple string blacklist. This CVSS 10.0 vulnerability allows attackers to bypass that check using standard shell features (e.g., specific character concatenation), leading to full Remote Code Execution (RCE).

A critical command injection vulnerability in terminal-controller-mcp allows attackers to bypass keyword-based filters and execute arbitrary code. By leveraging shell command substitution, malicious actors can reconstruct forbidden commands at runtime, rendering the application's blacklist security mechanism useless.

The Hook: Giving AI the Keys to the Castle

The Model Context Protocol (MCP) is the new hotness in the AI world. It’s essentially a standardized way for Large Language Models (LLMs) to interface with local tools, databases, and—in this specific case—your system terminal. The terminal-controller-mcp package does exactly what it says on the tin: it exposes a server that allows an AI (or anyone controlling the prompt) to execute shell commands on the host machine.

From a security perspective, this is the digital equivalent of handing a loaded shotgun to a toddler and hoping they don't pull the trigger. The premise of the tool requires exec capabilities by design. The developers knew this was risky, so they implemented a safety mechanism. They decided to act as a nanny, filtering out "bad words" before passing the command to the system shell.

Unfortunately, as history has taught us time and time again, trying to secure a shell interpreter by grepping for bad strings is a fool's errand. It’s not just a vulnerability; it’s a fundamental misunderstanding of how command shells parse input.

The Flaw: The Futility of Blacklists

The core issue lies in the execute_command function. The developers implemented a blacklist—a list of specific strings that are strictly forbidden. If you try to run rm -rf / or mkfs, the Python code spots the substring, wags its finger at you, and returns a security warning.

Here is the logic flaw: Python sees a string of characters, but the Shell sees a programming language. Python checks the input statically before execution. The Shell evaluates the input dynamically during execution. If you can make the input look safe to Python but dangerous to the Shell, you win.

This is a classic "Time of Check to Time of Use" (TOCTOU) logical gap, but specifically regarding parsing context. The Python filter is looking for the literal sequence m-k-f-s. It does not understand that in Bash, $(echo mkfs) is semantically identical to mkfs.

The Code: A Fragile Shield

Let's look at the vulnerable code in terminal_controller.py. It’s short, readable, and dangerously naive. It effectively tries to secure the system by checking if a substring exists within the user input.

# Inside terminal_controller.py
 
def execute_command(self, command: str) -> str:
    # The fatal mistake: A static blacklist
    dangerous_commands = ["rm -rf /", "mkfs"]
    
    # The check
    if any(dc in command.lower() for dc in dangerous_commands):
        return "For security reasons, this command is not allowed."
    
    try:
        # The execution
        result = subprocess.run(
            command,
            shell=True,  # <--- The root of all evil
            capture_output=True,
            text=True,
            timeout=timeout
        )
        return result.stdout
    except Exception as e:
        return str(e)

The presence of shell=True is the final nail in the coffin. It tells Python to pass the entire string to /bin/sh (or cmd.exe) for parsing. This enables piping, redirection, and variable expansion—features that the simple if statement above completely ignores.

The Exploit: Spelling It Out

To exploit this, we don't need buffer overflows or heap spraying. We just need to be creative with string concatenation. We want to execute mkfs (make file system) to wipe a drive, but we can't type "mkfs".

We can use shell command substitution $() to construct the command character by character. The Python filter will see a bunch of echo commands, which aren't on the blacklist. The Shell, however, will execute the inner commands first, assemble the string, and then execute the result.

The Attack Payload:

echo "$($(echo -n m; echo -n k; echo -n f; echo -n s))"

The Execution Flow:

  1. Python Check: Does the string contain "mkfs"? No. It contains "echo", "-n", "m", ";", etc. The check passes.
  2. Shell Execution: The shell parses the outer $().
  3. Inner Shell: Executes echo -n m, echo -n k, etc. The result is the string mkfs.
  4. Final Execution: The shell takes that result and runs it. The drive is formatted.

This technique is robust and works against almost any keyword-based filter that doesn't account for shell meta-characters.

The Impact: Total Ownership

Because terminal-controller-mcp is designed to run shell commands, the impact of bypassing the filter is effectively total system compromise. The severity is rated Critical (10.0) for a reason.

If this package is running inside a Docker container, the attacker has root inside that container. If the container is privileged or shares mounts with the host, escape is likely. If the user installed this locally to let their AI assistant "help with coding," the attacker now has the same permissions as that developer—access to SSH keys, source code, and AWS credentials.

This isn't just about wiping drives with mkfs. An attacker can just as easily construct a reverse shell using the same obfuscation techniques to maintain persistent access without ever triggering the "dangerous command" filter.

Technical Appendix

CVSS Score
10.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.68%
Top 29% most exploited

Affected Systems

terminal-controller-mcp v0.1.5terminal-controller-mcp v0.1.6terminal-controller-mcp v0.1.7

Affected Versions Detail

Product
Affected Versions
Fixed Version
terminal-controller-mcp
GongRzhe
<= 0.1.7TBD
AttributeDetail
CWE IDCWE-78 (OS Command Injection)
CVSS v3.110.0 (Critical)
Attack VectorNetwork
Privileges RequiredNone
Exploit StatusProof-of-Concept Available
EPSS Score0.00682

MITRE ATT&CK Mapping

T1059.004Unix Shell
Execution
T1027Obfuscated Files or Information
Defense Evasion
CWE-78
Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.

Known Exploits & Detection

GitHub IssueOriginal report detailing the keyword fragmentation bypass

Vulnerability Timeline

Vulnerability reported via GitHub Issue
2025-09-16
CVE-2025-61492 Assigned
2026-01-07
GHSA Advisory Published
2026-01-08

References & Sources

  • [1]GitHub Advisory
  • [2]Issue #7: Command Injection Report

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.