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
2. Complex Subprocess Management
# ❌ Tedious boilerplate everywhere
process = subprocess.Popen(['nmap', ...], stdout=subprocess.PIPE)
# Handle stdout, stderr, timeouts, errors...
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"
})
})
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
]
})
})
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();
}
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}]}'
Key Features
1. Built-in Concurrency Control
SCAN_LIMIT = asyncio.Semaphore(3) # Max 3 concurrent scans
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."
}
⚠️ 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
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
After:
# 5 lines, clean and safe
response = requests.post('http://localhost:8000/scan', json={
'target': target,
'options': [{'id': 30}, {'id': 50, 'value': ports}]
})
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
}
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
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)