VYPR
Moderate severityNVD Advisory· Published Mar 3, 2026· Updated Mar 4, 2026

PhialsBasement nmap-mcp-server Nmap CLI index.ts child_process.exec command injection

CVE-2026-3484

Description

A vulnerability was detected in PhialsBasement nmap-mcp-server up to bee6d23547d57ae02460022f7c78ac0893092e38. Affected by this issue is the function child_process.exec of the file src/index.ts of the component Nmap CLI Command Handler. The manipulation results in command injection. The attack may be performed from remote. This product utilizes a rolling release system for continuous delivery, and as such, version information for affected or updated releases is not disclosed. The patch is identified as 30a6b9e1c7fa6146f51e28d6ab83a2568d9a3488. It is best practice to apply a patch to resolve this issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Command injection in nmap-mcp-server's runNmapScan function allows remote attackers to execute arbitrary commands via unsanitized additionalFlags input.

Vulnerability

Overview

CVE-2026-3484 describes a command injection vulnerability in the PhialsBasement nmap-mcp-server, a Model Context Protocol (MCP) server that enables AI assistants to perform network scanning using Nmap [3]. The flaw resides in the runNmapScan function within src/index.ts, which uses child_process.exec to construct and execute shell commands. User-supplied parameters, particularly additionalFlags, are passed directly to exec() without sufficient validation or escaping, allowing an attacker to inject shell metacharacters such as ;, &&, or others to execute arbitrary commands [4].

Exploitation

The attack can be performed remotely, as the MCP server is designed to accept tool calls from AI assistants over a network [1][3]. The vulnerable code path does not sanitize the additionalFlags parameter, meaning any client that can invoke the run_nmap_scan tool can inject malicious commands. The official patch, identified by commit 30a6b9e1c7fa6146f51e28d6ab83a2568d9a3488, replaces exec() with execFile() and introduces a strict allowlist of permitted Nmap flags, along with validation to reject dangerous characters [2].

Impact

Successful exploitation leads to arbitrary command execution on the server hosting the nmap-mcp-server. An attacker could leverage this to compromise the host system, exfiltrate data, or pivot to other network resources. The product uses a rolling release model, so specific version numbers for affected releases are not disclosed, but the vulnerability exists in all versions up to the commit bee6d23547d57ae02460022f7c78ac0893092e38 [1].

Mitigation

The maintainer has provided a patch in commit 30a6b9e1c7fa6146f51e28d6ab83a2568d9a3488, which should be applied immediately [2]. Users are advised to update their installations to the latest commit. As a best practice, the server should not be exposed to untrusted networks, and input validation should be enforced at the application layer.

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
mcp-nmap-servernpm
<= 1.0.1

Affected products

2
  • Range: < 30a6b9e1c7fa6146f51e28d6ab83a2568d9a3488 (commit level)
  • PhialsBasement/nmap-mcp-serverv5
    Range: bee6d23547d57ae02460022f7c78ac0893092e38

Patches

1
30a6b9e1c7fa

Fix command injection in runNmapScan by using execFile

1 file changed · +93 45
  • src/index.ts+93 45 modified
    @@ -4,10 +4,54 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
     import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
     import { z } from "zod";
     import { zodToJsonSchema } from "zod-to-json-schema";
    -import { exec } from 'child_process';
    +import { execFile } from 'child_process';
     import { promisify } from 'util';
     
    -const execAsync = promisify(exec);
    +const execFileAsync = promisify(execFile);
    +
    +// Whitelist of allowed nmap flags for security  
    +const ALLOWED_FLAGS = [  
    +    '-sS', '-sT', '-sA', '-sW', '-sM', '-sU', '-sN', '-sF', '-sX',  
    +    '-O', '-sV', '-sC', '-F', '-p-', '-v', '--open', '--reason',  
    +    '-Pn', '-PP', '-PM', '-PO', '-PE', '-PS', '-PA', '-PU', '-PY',  
    +    '-6', '-4', '-b', '-D', '-S', '-e', '-g', '-f', '-i', '-M', '-o',  
    +    '-R', '-r', '-T', '-V'  
    +];  
    +  
    +// Validate additionalFlags for security to prevent command injection  
    +function validateAdditionalFlags(flags: string): boolean {  
    +    if (!flags || typeof flags !== 'string') {  
    +        return false;  
    +    }  
    +      
    +    // Split flags and filter empty strings  
    +    const flagArray = flags.split(' ').filter(f => f.trim());  
    +      
    +    // Check each flag against whitelist and dangerous characters  
    +    return flagArray.every(flag => {  
    +        // Check if it's an allowed single flag  
    +        if (ALLOWED_FLAGS.includes(flag)) {  
    +            return true;  
    +        }  
    +          
    +        // Check if it's a safe parameterized flag  
    +        if (flag.startsWith('--script=') && flag.length > 9) {  
    +            return true; // Allow --script parameter  
    +        }  
    +          
    +        if (flag.startsWith('-p') && flag.length > 2) {  
    +            return true; // Allow -p parameter  
    +        }  
    +          
    +        if (flag.startsWith('-d') && /^\d+$/.test(flag.slice(2))) {  
    +            return true; // Allow debug level  
    +        }  
    +          
    +        // Check for dangerous characters that could enable injection  
    +        const dangerousChars = [';', '&', '|', '`', '$', '(', ')', '<', '>', '"', "'"];  
    +        return !dangerousChars.some(char => flag.includes(char));  
    +    });  
    +}
     
     // Schema definitions for NMAP scanning
     const NmapScanSchema = z.object({
    @@ -27,48 +71,52 @@ const server = new Server({
         },
     });
     
    -async function runNmapScan(params: z.infer<typeof NmapScanSchema>) {
    -    const { target, ports, scanType, timing, additionalFlags } = params;
    -    
    -    // Build the nmap command with proper flags
    -    let command = `nmap -T${timing}`;
    -    
    -    // Add scan type flags
    -    switch (scanType) {
    -        case 'quick':
    -            command += ' -F';  // Fast scan
    -            break;
    -        case 'full':
    -            command += ' -p-';  // All ports
    -            break;
    -        case 'version':
    -            command += ' -sV';  // Version detection
    -            break;
    -    }
    -    
    -    // Add port specification if provided
    -    if (ports) {
    -        command += ` -p${ports}`;
    -    }
    -    
    -    // Add any additional flags
    -    if (additionalFlags) {
    -        command += ` ${additionalFlags}`;
    -    }
    -    
    -    // Add target
    -    command += ` ${target}`;
    -
    -    try {
    -        const { stdout, stderr } = await execAsync(command);
    -        if (stderr) {
    -            console.error('Nmap stderr:', stderr);
    -        }
    -        return stdout;
    -    } catch (error: unknown) {
    -        const errorMessage = error instanceof Error ? error.message : String(error);
    -        throw new Error(`Nmap scan failed: ${errorMessage}`);
    -    }
    +async function runNmapScan(params: z.infer<typeof NmapScanSchema>) {  
    +    const { target, ports, scanType, timing, additionalFlags } = params;  
    +      
    +    // Build arguments array instead of command string for security  
    +    const args = [`-T${timing}`];  
    +      
    +    // Add scan type flags  
    +    switch (scanType) {  
    +        case 'quick':  
    +            args.push('-F');  // Fast scan  
    +            break;  
    +        case 'full':  
    +            args.push('-p-');  // All ports  
    +            break;  
    +        case 'version':  
    +            args.push('-sV');  // Version detection  
    +            break;  
    +    }  
    +      
    +    // Add port specification if provided  
    +    if (ports) {  
    +        args.push('-p', ports);  
    +    }  
    +      
    +    // Validate and add additional flags with security check  
    +    if (additionalFlags) {  
    +        if (!validateAdditionalFlags(additionalFlags)) {  
    +            throw new Error('Invalid or dangerous additional flags detected');  
    +        }  
    +        args.push(...additionalFlags.split(' ').filter(f => f.trim()));  
    +    }  
    +      
    +    // Add target as last argument  
    +    args.push(target);  
    +  
    +    try {  
    +        // Use execFile instead of exec to prevent shell injection  
    +        const { stdout, stderr } = await execFileAsync('nmap', args);  
    +        if (stderr) {  
    +            console.error('Nmap stderr:', stderr);  
    +        }  
    +        return stdout;  
    +    } catch (error: unknown) {  
    +        const errorMessage = error instanceof Error ? error.message : String(error);  
    +        throw new Error(`Nmap scan failed: ${errorMessage}`);  
    +    }  
     }
     
     // Tool handlers
    @@ -125,4 +173,4 @@ async function runServer() {
     runServer().catch((error) => {
         console.error("Fatal error running server:", error);
         process.exit(1);
    -});
    \ No newline at end of file
    +});
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.