[ ⌘K ]
← BACK TO SEARCH

stefanskiasan/semgrep-mcp-server

critical

No description

This MCP server integrates Semgrep, a static code analysis tool, into development environments via the Model Context Protocol. It allows users to scan...

purpose: This MCP server integrates Semgrep, a static code threat: local with credentials
JavaScript2May 20, 2026May 20, 2026GITHUB
5/20/2026
high1 finding
src/index.ts
436      await execAsync(`echo '${ruleYaml}' > ${outputPath}`);
src/index.ts:10src/index.ts:15

// 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.

high1 finding
src/index.ts
303      const { stdout, stderr } = await execAsync(
304        `semgrep scan --json --config ${configParam} ${scanPath}`
305      );
src/index.ts:10src/index.ts:15

// 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.

high1 finding
src/index.ts
592      await execAsync(`echo '${output}' > ${outputFile}`);
src/index.ts:10src/index.ts:15

// 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.

high1 finding
src/index.ts
487        const pathRegex = new RegExp(args.path_pattern);
src/index.ts:10src/index.ts:15

// 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.

medium1 finding
src/index.ts
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  }
src/index.ts:12

// 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.

medium1 finding
src/index.ts
329    const languageFilter = args.language ? `--lang ${args.language}` : '';
src/index.ts:10src/index.ts:15

// 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.

network.httpshell.execauth.none
100
LLM-based
high findings+100
medium findings+30