DEV Community

Cover image for Building Web-Based Nmap Tools: Introducing nmap-exec-api
Muhammed Shafin P
Muhammed Shafin P

Posted on

Building Web-Based Nmap Tools: Introducing nmap-exec-api

The Problem Every Developer Faces

Want to integrate Nmap into your web application? You'll quickly run into three major problems:

1. Security Nightmares

# ❌ Dangerous: Shell injection vulnerability
os.system(f"nmap {user_input}")  # One malicious input = compromised system
Enter fullscreen mode Exit fullscreen mode

2. Complex Subprocess Management

# ❌ Tedious boilerplate everywhere
process = subprocess.Popen(['nmap', ...], stdout=subprocess.PIPE)
# Handle stdout, stderr, timeouts, errors...
Enter fullscreen mode Exit fullscreen mode

3. Cross-Language Hell

Frontend in React? Mobile app in Flutter? Good luck integrating Python subprocess code.

The Solution: nmap-exec-api

I built a lightweight FastAPI wrapper that lets you control Nmap using simple JSON requests—no shell commands, no subprocess headaches.

GitHub: https://github.com/hejhdiss/nmap-exec-api

Instead of This (Unsafe):

// Dangerous: Raw command execution
fetch('/run', {
  body: JSON.stringify({ 
    command: "nmap -sS -p 1-1000 192.168.1.1" 
  })
})
Enter fullscreen mode Exit fullscreen mode

Do This (Safe):

// Safe: Structured options via IDs
fetch('http://localhost:8000/scan', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    target: "192.168.1.1",
    options: [
      { id: 30 },                  // TCP SYN scan
      { id: 50, value: "1-1000" }  // Port range
    ]
  })
})
Enter fullscreen mode Exit fullscreen mode

How It Works: The ID System

Instead of memorizing complex flags, use numeric IDs:

ID Nmap Flag Description
30 -sS TCP SYN scan
50 -p Port specification
70 -sV Service version detection
150 -oN Output to file

Benefits:

  • Language-agnostic (any language can send integers)
  • Type-safe (no string concatenation)
  • Self-documenting (clear option catalog)
  • No shell injection (structured input only)

Real-World Example: Security Dashboard

// React Component
async function runScan(target) {
  const response = await fetch('http://localhost:8000/scan', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      target: target,
      options: [
        { id: 30 },              // SYN scan
        { id: 70 },              // Version detection
        { id: 50, value: "80,443,8080" },
        { id: 153 }              // Verbose output
      ]
    })
  });

  return await response.json();
}
Enter fullscreen mode Exit fullscreen mode

Quick Start

# Install
git clone https://github.com/hejhdiss/nmap-exec-api.git
cd nmap-exec-api
pip install fastapi uvicorn

# Run
uvicorn nmap-testing:app --host 0.0.0.0 --port 8000

# Test
curl -X POST "http://localhost:8000/scan" \
  -H "Content-Type: application/json" \
  -d '{"target": "scanme.nmap.org", "options": [{"id": 30}]}'
Enter fullscreen mode Exit fullscreen mode

Key Features

1. Built-in Concurrency Control

SCAN_LIMIT = asyncio.Semaphore(3)  # Max 3 concurrent scans
Enter fullscreen mode Exit fullscreen mode

2. Safe File Handling

  • Automatically creates directories
  • Prevents file overwrites
  • Returns absolute paths

3. Clear Error Messages

{
  "error": "Output file already exists. Please choose a different file name."
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Critical: Security Considerations

This API is a foundation—YOU must add security layers:

What's NOT Validated:

❌ File path traversal attacks

❌ Target authorization/whitelisting

❌ Authentication/Authorization

❌ Rate limiting per user

What YOU Must Add:

# Example: Path validation
def validate_output_path(path: str, allowed_dir: str = "/var/nmap/outputs"):
    abs_path = os.path.abspath(path)
    if not abs_path.startswith(os.path.abspath(allowed_dir)):
        raise ValueError("Invalid path")
    return abs_path

# Example: Target whitelisting
ALLOWED_NETWORKS = ["192.168.1.0/24", "10.0.0.0/8"]

# Example: Add authentication
@app.post("/scan")
async def scan(req: ScanRequest, token: str = Depends(verify_token)):
    # Verify permissions first
    pass
Enter fullscreen mode Exit fullscreen mode

Deploy with:
✅ Authentication (OAuth2, JWT, API keys)

✅ Rate limiting

✅ Network whitelisting

✅ Containerized environment

✅ Activity logging

Use Cases

Web Dashboards
Build React/Vue/Angular security monitoring interfaces

Automation
Integrate into CI/CD pipelines, scheduled scans, alerting systems

Mobile Apps
Create iOS/Android network scanning tools

Internal Tools
Custom security dashboards for your organization

Why Use This?

Time Savings

✅ No subprocess management code

✅ No option parsing logic

✅ No concurrency handling

✅ Works with any language

Before vs After

Before:

# 50+ lines of subprocess management, error handling, parsing...
cmd = f"nmap -sS -p {ports} {target}"  # Shell injection risk!
process = subprocess.Popen(cmd, shell=True, ...)
# Handle everything manually
Enter fullscreen mode Exit fullscreen mode

After:

# 5 lines, clean and safe
response = requests.post('http://localhost:8000/scan', json={
    'target': target,
    'options': [{'id': 30}, {'id': 50, 'value': ports}]
})
Enter fullscreen mode Exit fullscreen mode

Extending the API

Adding new Nmap options is trivial:

SCAN_TECHNIQUES = {
    30: {"flag": "-sS", "needs_input": False},
    # Add your option:
    42: {"flag": "-sY", "needs_input": False}  # SCTP scan
}
Enter fullscreen mode Exit fullscreen mode

No API changes needed. Clients automatically get new options.

Integration Example: Python with Auth

from fastapi import Depends, HTTPException
from fastapi.security import APIKeyHeader

api_key_header = APIKeyHeader(name="X-API-Key")

async def verify_key(api_key: str = Depends(api_key_header)):
    if api_key != "your-secret-key":
        raise HTTPException(status_code=403)
    return api_key

@app.post("/scan")
async def scan(req: ScanRequest, key: str = Depends(verify_key)):
    # Proceed with authenticated scan
    pass
Enter fullscreen mode Exit fullscreen mode

Get Started

Repository: https://github.com/hejhdiss/nmap-exec-api

License: Apache 2.0 (free to use, modify, and integrate commercially)

Contributions Welcome:

  • Report bugs
  • Suggest features
  • Submit PRs
  • Star the repo ⭐

Legal Disclaimer

For authorized security testing only. Always get explicit permission before scanning any target. Unauthorized network scanning may be illegal. The author is not responsible for misuse.


Built by: Muhammed Shafin P (@hejhdiss)

Building web-based security tools just got easier. Start integrating Nmap today!

Top comments (0)