CVE-2026-55581 Overview
CVE-2026-55581 is a command injection vulnerability in mcp-shell, a Model Context Protocol (MCP) server that executes shell commands on demand. Versions prior to 0.6.0 ship a default Docker security.yaml that includes /bin/bash in the allowed_executables list. The validation logic in security.go inspects only the first token of the requested command and does not reject the shell command-mode flag -c. A caller of the shell_exec MCP tool can supply /bin/bash -c <arbitrary-command> to bypass the allowlist. The command reaches executor.go, where parseCommand and exec.CommandContext execute it as the mcpuser account. The issue is fixed in version 0.6.0.
Critical Impact
Any client authorized to call the shell_exec MCP tool can execute arbitrary shell commands as mcpuser, defeating the executable allowlist entirely.
Affected Products
- sonirico/mcp-shell versions prior to 0.6.0
- Deployments using the default Docker security.yaml that includes /bin/bash in allowed_executables
- MCP server integrations exposing the shell_exec tool to LLM agents or remote callers
Discovery Timeline
- 2026-08-25 - CVE-2026-55581 published to the National Vulnerability Database (NVD)
- 2026-08-25 - Last updated in NVD database
- Fixed in v0.6.0 - Patch published in GitHub Release v0.6.0 and GHSA-3x77-wg38-92r3
Technical Details for CVE-2026-55581
Vulnerability Analysis
The flaw is an OS Command Injection [CWE-78] caused by incomplete allowlist enforcement. mcp-shell intends to constrain callers of shell_exec to a fixed list of executables defined in AllowedExecutables. The validation function tokenizes the incoming command and checks the first token against this allowlist. Because /bin/bash is present in the default configuration, that check passes for any argument list that begins with /bin/bash. The secondary function checkBlockedPatternsAndCommands does not treat -c as a signal that the following argument is a fresh shell command to inspect. The remaining arguments are handed to parseCommand and executed by exec.CommandContext, which spawns bash in command-mode and runs whatever the caller supplied.
Root Cause
Two design decisions combine to produce the vulnerability. First, an interpreter (/bin/bash) is included in the default allowed_executables list, meaning the allowlist covers the launcher but not the code that launcher will run. Second, the validator does not recognize the semantics of bash -c, so it fails to descend into the -c argument and re-apply command checks. This is a classic allowlist-bypass where the trusted binary is itself a general-purpose executor.
Attack Vector
The vulnerability requires local access to the MCP server transport, matching the AV:L designation. In practice, that transport is often exposed to an LLM agent or an adjacent process on the same host. A caller invokes the shell_exec MCP tool with a command argument of the form /bin/bash -c "<payload>". Validation approves the request because the first token is on the allowlist. The executor then runs the payload as mcpuser, granting the attacker the full privileges of that account, including read and write access to files it owns and any secrets available to the container.
// Patched SecurityConfig struct from config.go
// Source: https://github.com/sonirico/mcp-shell/commit/f31377fce6ec31114e5a4398c0e5270552bce09f
type SecurityConfig struct {
Enabled bool `yaml:"enabled"`
AllowedCommands []string `yaml:"allowed_commands"` // Deprecated: use AllowedExecutables
BlockedCommands []string `yaml:"blocked_commands"` // Deprecated: use validation instead
BlockedPatterns []string `yaml:"blocked_patterns"` // Deprecated: use validation instead
AllowedExecutables []string `yaml:"allowed_executables"` // Secure: list of allowed executable paths
MaxExecutionTime time.Duration `yaml:"max_execution_time"`
WorkingDirectory string `yaml:"working_directory"`
RunAsUser string `yaml:"run_as_user"`
MaxOutputSize int `yaml:"max_output_size"`
AuditLog bool `yaml:"audit_log"`
UseShellExecution bool `yaml:"use_shell_execution"` // Legacy mode - enables shell execution (DANGEROUS)
}
The 0.6.0 patch makes secure mode the default and keeps interpreters such as /bin/bash out of the shipped allowlist. See the security patch commit and Pull Request #16 for full changes.
Detection Methods for CVE-2026-55581
Indicators of Compromise
- Audit log entries from mcp-shell where the shell_exec tool receives a command value beginning with /bin/bash -c, /bin/sh -c, or any interpreter followed by -c
- Child processes of the mcp-shell binary running as mcpuser that are not on the intended allowlist, such as curl, wget, nc, python, or outbound shell invocations
- Unexpected file writes or network egress originating from the mcp-shell container or process tree
Detection Strategies
- Enable the audit_log option in security.yaml and alert on any command argument containing the -c flag paired with an interpreter path
- Baseline the expected process tree for the mcp-shell service and flag deviations, particularly interpreters spawning non-allowlisted children
- Review MCP transport logs for shell_exec invocations that do not match the operator's documented use cases
Monitoring Recommendations
- Ship mcp-shell audit logs and container process telemetry to a centralized logging platform for correlation and retention
- Monitor for the mcpuser account performing actions outside its declared scope, including credential access, package installs, or outbound connections
- Track deployed mcp-shell versions across the fleet and alert when instances remain on releases earlier than 0.6.0
How to Mitigate CVE-2026-55581
Immediate Actions Required
- Upgrade mcp-shell to version 0.6.0 or later, which removes interpreters from the default allowlist and enables secure mode by default
- Audit any custom security.yaml files and remove /bin/bash, /bin/sh, python, perl, ruby, and similar interpreters from allowed_executables
- Restrict who can reach the MCP transport exposing shell_exec, treating it as a privileged administrative interface
Patch Information
The fix is available in mcp-shell v0.6.0. The change is described in Pull Request #16 and the GHSA-3x77-wg38-92r3 advisory. The patch makes secure mode the default configuration and stops shipping shell interpreters in allowed_executables.
Workarounds
- Replace /bin/bash in allowed_executables with the specific binaries the deployment actually requires, using absolute paths
- Set use_shell_execution: false to disable legacy shell execution mode on unpatched installations
- Run the mcp-shell container with a read-only root filesystem, dropped capabilities, and no outbound network access unless explicitly needed
# Example hardened security.yaml fragment
security:
enabled: true
use_shell_execution: false
allowed_executables:
- /usr/bin/ls
- /usr/bin/cat
- /usr/bin/grep
run_as_user: mcpuser
audit_log: true
max_execution_time: 10s
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

