The vulnerability is a classic command injection flaw within the mcp-maigret Node.js server. The root cause lies in the MaigretServer.handleToolRequest method, which dynamically constructed a docker run command as a single string. This string incorporated unsanitized user input from the username, url, and tags parameters. The composed command string was then passed to the MaigretServer.execCommand method, which utilized child_process.exec. The use of exec is dangerous because it spawns a shell to execute the command, meaning any shell metacharacters (like ;, |, &, $()) in the user input would be interpreted and executed by the shell.
The patch addresses this vulnerability in multiple ways:
- Replacing
exec with execFile: The execCommand function was fundamentally changed to use child_process.execFile. Unlike exec, execFile does not spawn a shell, and it accepts the command and its arguments as an array. This is the primary mitigation, as it prevents the operating system from interpreting metacharacters within the arguments.
- Argument-based Command Execution: Instead of concatenating a single command string, the code now builds an array of arguments (
dockerArgs) and passes it to the new execFile-based execCommand. This ensures a clean separation between the command and its parameters.
- Input Validation: Strict validation functions (
isValidUsername, isValidUrl, isValidTag) were introduced and are now used within handleToolRequest to reject any input containing characters that are not explicitly allowed. This provides an additional layer of defense.
During exploitation, a profiler would show MaigretServer.handleToolRequest being called, which in turn calls the vulnerable version of MaigretServer.execCommand. Both functions are critical to the execution of the injected command.