# mcp-shell has a Secure Mode Allowlist Bypass via Git Shell Alias

mcp-shell's secure-mode metacharacter blocklist omits '!', so an allowed /usr/bin/git with `-c alias.pwn=!CMD` executes arbitrary shell commands as mcpuser.

- Payout: Research
- Severity: high
- Program: mcp-shell
- Found by: EQSTLab
- Disclosed: 2026-08-25
- CVE: CVE-2026-55582
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-74hp-mggr-hv58
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-74hp-mggr-hv58
- Tags: area:ai domain:ai domain:infra impact:rce kind:research platform:ghsa sev:high tech:docker tech:go technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** MCP shell_exec tool / security.yaml allowlist validator
**Root cause:** The secure-mode validator blocks `|&;<>(){}[]$`` but not `!`, and applies no per-executable argument policy, so Git's `-c alias.NAME=!CMD` shell-alias syntax passes validation and executes CMD via sh.
**Steps:**
1. Build the default Docker image with git installed, security.yaml allowing /usr/bin/git, blocked_patterns empty, running as mcpuser.
2. Send MCP initialize and notifications/initialized over stdin.
3. Send `tools/call` for `shell_exec` with `command` = `/usr/bin/git -c alias.pwn=!touch pwn /tmp/mcp-shell-mcp-poc`.
4. Validator passes: `!` absent from containsShellMetacharacters and containsDangerousShellConstructs; /usr/bin/git matches AllowedExecutables.
5. executor.go runs `exec.CommandContext(ctx, "/usr/bin/git", "-c", "alias.pwn=!touch", "pwn", "/tmp/target")`; git resolves alias pwn and runs `sh -c 'touch "$@"' _ /tmp/target`.
6. Observe evidence file created with uid=1000 on the bind-mounted host /tmp.
**How found:** Reviewed the secure-mode validator's metacharacter blocklist against the default allowlisted executables; noticed `!` missing and that git's `-c alias.*=!` runtime config turns an allowed binary into a shell executor.
**Exploitation:** Any MCP client (or LLM prompt driving an agent) that can issue tools/call to shell_exec sends the git alias payload; no auth beyond MCP connectivity. Git executes the alias as a shell command, giving arbitrary command execution as mcpuser (UID 1000) inside the default container.
**Escalation:** Chained into AI agent tooling: a malicious/compromised LLM prompt supplies the payload as the command argument, turning prompt influence into host-container RCE.
**Insight:** When an allowlist permits a general-purpose binary like git, audit that binary's own config/flag surface for shell-execution primitives (`-c alias.x=!cmd`, `core.pager`, `core.editor`, `--exec-path`) rather than only blocking shell metacharacters.

## Proof of concept (copied exactly from the original report)

**MCP tools/call request with git alias payload**

```
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "shell_exec",
    "arguments": {
      "command": "/usr/bin/git -c alias.pwn=!touch pwn /tmp/mcp-shell-mcp-poc",
      "base64": false
    }
  }
}
```

