T09 · Insecure Skill Coding Practices
- Location
scripts/nmap_pentest_scans.py:64- Finding
Shell Command Injection Through Unvalidated Target Values in Generated Nmap Commands
- Content
View full analysis
Vulnerability Details
File Location:
scripts/nmap_pentest_scans.py, lines 64-119 and 158-161
Vulnerability Type: Shell command injection in generated command artifacts
Risk Level: HighVulnerable Code
python def build_command_plan(target: str, profile: str, include_udp: bool) -> list[dict[str, str]]: target_basename = normalize_target_basename(target) if profile == "stealth": timing = "-T2" rate = "--max-retries 2 --scan-delay 5ms" elif profile == "fast": timing = "-T4" rate = "--min-rate 500 --max-retries 1 --host-timeout 10m" else: timing = "-T3" rate = "--min-rate 100 --max-retries 2" plan: list[dict[str, str]] = [ { "stage": "host-discovery", "command": ( f"nmap -sn {target} -n --reason " f"-oA results/{target_basename}-01-discovery" ), "purpose": "Detect responsive hosts and collect probe reasons.", }, { "stage": "tcp-triage", "command": ( f"nmap -sS --top-ports 1000 {target} -n {timing} {rate} --reason " f"-oA results/{target_basename}-02-tcp-top1000" ), "purpose": "Find common exposed TCP services quickly.", }, { "stage": "service-enum", "command": ( f"nmap -sV -sC -p <OPEN_TCP_PORTS> {target} -n {timing} --reason " f"-oA results/{target_basename}-03-svc-default" ), "purpose": "Fingerprint service versions and run default safe scripts.", }, { "stage": "web-tls", "command": ( f"nmap -p 80,443 --script http-title,http-headers,http-methods,ssl-cert " f"{target} -n --script-timeout 30s " f"-oA results/{tar ...[truncated 3217 chars]- Remediation
View remediation
Remediation Suggestions
- Parse targets using strict allowlists:
- Use Python's
ipaddressmodule for IPv4, IPv6, and CIDR values. - Validate DNS names label by label.
- Reject whitespace, control characters, newlines, shell metacharacters, leading hyphens, and unsupported Nmap target expressions.
- Use Python's
- Represent commands internally as argument arrays rather than shell strings, for example:
python command = ["nmap", "-sn", validated_target, "-n", "--reason", "-oA", output_prefix] - If live execution is later implemented, use
subprocess.run(command, shell=False, check=True)and never pass target-derived strings through a shell. - If human-readable shell commands must be exported, serialize every argument with
shlex.quote()and clearly mark the file as informational rather than executable. - Test rejection of semicolons, pipes, command substitutions, redirections, embedded newlines, whitespace-separated extra arguments, and targets beginning with
-. - Keep output-path normalization, but do not mistake filename normalization for command-argument validation.
- Parse targets using strict allowlists:
