stefanskiasan/semgrep-mcp-server
criticalNo description
This MCP server integrates Semgrep, a static code analysis tool, into development environments via the Model Context Protocol. It allows users to scan...
436 await execAsync(`echo '${ruleYaml}' > ${outputPath}`);// Local-only MCP, requires compromised LLM to exploit
The handleCreateRule method constructs a YAML string from user-supplied pattern, message, language, and severity parameters and passes it directly to a shell command via execAsync. Although the output_path is validated, the rule content is not sanitized, allowing injection of arbitrary shell commands through single quotes or backticks in the pattern, message, or language fields.
ImpactAn attacker with control over the LLM prompt could execute arbitrary shell commands on the host system by injecting shell metacharacters into the pattern, message, or language parameters. This could lead to full system compromise.
FixUse a YAML library to construct the rule file instead of string interpolation, or properly escape shell arguments. Avoid using execAsync with unsanitized input.
303 const { stdout, stderr } = await execAsync(
304 `semgrep scan --json --config ${configParam} ${scanPath}`
305 );// Local-only MCP, requires compromised LLM to exploit
The config parameter is validated as an absolute path only when it is not 'auto'. However, the validation only checks that it is an absolute path within the allowed base directory, but does not prevent shell injection via spaces or special characters in the path. Additionally, if config is 'auto', it is passed directly without any sanitization. An attacker could inject shell commands by providing a config value like 'auto; malicious_command' or a path containing shell metacharacters.
ImpactAn attacker could execute arbitrary shell commands on the host system by injecting into the config parameter, leading to full system compromise.
FixUse execFile or spawn with argument array instead of execAsync to avoid shell interpretation. Validate that config is either 'auto' or a safe path without shell metacharacters.
592 await execAsync(`echo '${output}' > ${outputFile}`);// Local-only MCP, requires compromised LLM to exploit
The export_results method constructs a shell command using the output variable, which is derived from JSON.parse of a file read via cat. While the output file path is validated, the output content is not sanitized. If an attacker can control the contents of the results file (e.g., by writing a malicious file via create_rule or other means), they can inject shell commands through single quotes or backticks in the output.
ImpactAn attacker could execute arbitrary shell commands by crafting a malicious results file that, when exported, injects commands into the shell command.
FixUse a file writing API (e.g., fs.writeFile) instead of shell redirection. Avoid using execAsync with unsanitized content.
487 const pathRegex = new RegExp(args.path_pattern);// Local-only MCP, requires compromised LLM to exploit
The path_pattern parameter is used to construct a RegExp object without any sanitization. While this is not a shell injection, it is a ReDoS (Regular Expression Denial of Service) vulnerability. An attacker could provide a malicious regex pattern that causes catastrophic backtracking, leading to CPU exhaustion and denial of service.
ImpactAn attacker could cause the server to hang or crash by providing a specially crafted regex pattern, leading to denial of service.
FixValidate or sanitize the regex pattern, or limit the complexity of allowed patterns. Consider using a regex parser with timeout.
81 private validateAbsolutePath(pathToValidate: string, paramName: string): string {
82 if (!path.isAbsolute(pathToValidate)) {
83 throw new McpError(...);
84 }
85 const normalizedPath = path.normalize(pathToValidate);
86 if (!path.isAbsolute(normalizedPath)) {
87 throw new McpError(...);
88 }
89 if (!normalizedPath.startsWith(BASE_ALLOWED_PATH)) {
90 throw new McpError(...);
91 }
92 return normalizedPath;
93 }// Local-only MCP, requires compromised LLM to exploit
The validateAbsolutePath function checks that the normalized path starts with BASE_ALLOWED_PATH, but it does not resolve symlinks. An attacker could create a symlink within the allowed directory that points to an arbitrary location outside the allowed path, bypassing the path restriction.
ImpactAn attacker could read or write files outside the intended directory by using symlinks, potentially accessing sensitive system files or overwriting critical files.
FixUse fs.realpathSync to resolve symlinks before checking the path prefix. Also consider using path.relative to ensure the resolved path is within the allowed base.
329 const languageFilter = args.language ? `--lang ${args.language}` : '';// Local-only MCP, requires compromised LLM to exploit
The language parameter is used directly in a shell command without validation. Although the command is 'semgrep login --help' which does not use the language filter, the variable is constructed but not used. However, if the code were to use it in the future, it would be vulnerable. Currently, it is dead code but indicates a pattern of unsanitized input.
ImpactCurrently no impact as the variable is unused, but it represents a latent vulnerability.
FixRemove unused code or properly validate and escape the language parameter if it is to be used.