August 25, 2026
AI-Powered Penetration Testing Automation with Python, Nmap, Gobuster & Groq
1.Introduction
By Ganeshmandla
12 min read
1.Introduction
This project is an AI-assisted penetration testing automation tool built with Python. The tool takes an authorized target from a target file, performs reconnaissance and vulnerability checks using Nmap and web enumeration using Gobuster, collects the results as pentest evidence, sends the processed evidence to a Groq-hosted AI model for analysis, and automatically generates an HTML penetration testing report.
example :
Authorized Target ↓ targets.txt ↓ Python Automation ↓ Nmap ────────────┐ │ Nmap NSE ─────────┤ ──→ Evidence
Gobuster ──────────┘ ↓ Python collects results ↓ OpenAI Python Library ↓ Groq API ↓ AI Model ↓ Security Analysis ↓ Python ↓ HTML Report ↓ Firefox
2. What Problem Does This Project Solve?
Explain the manual process first.
Normally, a pentester may have to manually:
Enter target ↓ Run Nmap ↓ Read results ↓ Run vulnerability checks ↓ Run Gobuster ↓ Read all output files ↓ Analyze findings ↓ Write report
This project automates much of that repetitive workflow.
Target ↓ One Python program ↓ Scanning ↓ Enumeration ↓ Evidence collection ↓ AI-assisted analysis ↓ Report
Important: This is AI-assisted pentesting, not an autonomous hacker. The security tools perform the scanning/enumeration, while the AI analyzes the collected evidence and helps generate the report.
3. Project Architecture
Python is the central component of the project. It connects the target file, security tools, result files, Groq API, AI response, and final HTML report together.
4. How the Automation Works
Python first runs Nmap, Nmap NSE, and Gobuster tools to collect scan and enumeration data from the target → it reads those results from files and prepares them as evidence → it sends the prepared data as a request to the Groq API using the OpenAI Python library → the Groq API verifies the GROQ_API_KEY for authentication → if the API key is valid, it forwards the request to the selected AI model → the AI model analyzes the Nmap, NSE, and Gobuster evidence and generates security findings and report content → the AI response is returned to the Python application → Python converts the response into HTML format and creates pentest_report.html → finally, Python opens Firefox and displays the generated HTML report to the user.
Target ↓ Python ↓ Security Tools ↓ Results ↓ Evidence ↓ Groq API ↓ Authentication ↓ AI Analysis ↓ Python ↓ HTML Report ↓ Firefox
5. Lab Environment
For example:
Kali Linux │ ├── Python ├── Nmap ├── Gobuster └── AI Pentest Project │ ↓ Authorized Lab Target
Example that the target should be:
- A machine you own
- A VulnHub/Metasploitable lab
- A CTF/lab environment
- Or another system for which you have explicit authorization
Do not use random public websites as targets.
6. Project Directory
Then create the project: mkdir ai-pentest-lab cd ai-pentest-lab
ai-pentest-lab/ │ ├── targets.txt ├── pentest_ai.py │ ├── nmap_results.txt ├── vuln_results.txt ├── gobuster_80.txt ├── gobuster_8180.txt │ └── pentest_report.html
What are these files?
targets.txt >Target input
pentest_ai.py >Main automation program
nmap_results.txt >Nmap scan results
vuln_results.txt >Nmap NSE vulnerability results
gobuster_80.txt >Gobuster results for HTTP port 80
gobuster_8180.txt >Gobuster results for HTTP port 8180
pentest_report.html >Final AI-generated report
7. Create the Target File
nano targets.txt
Example: 10.0.2.99
targets.txt acts as the input to the automation. Instead of hard-coding the target inside the Python program, the program reads it from this file.
cat targets.txt
10.0.2.99
8. Install the Required Security Tools
before giving commands.
Update package information
sudo apt update
Install Nmap
Nmap : sudo apt install nmap -y
Purpose:
Nmap is used to discover open ports, services, and versions.
Purpose
Nmap is used for network and service enumeration.
It can help identify:
- Open ports
- Running services
- Service versions
22/tcp open ssh 80/tcp open http 8180/tcp open http
Nmap NSE
Nmap also includes the Nmap Scripting Engine (NSE).
The project can use:
nmap -sV — script vuln
The --script vuln option runs applicable vulnerability-checking scripts.
Nmap ↓ Service discovery
Nmap NSE ↓ Vulnerability checks
Install Gobuster
sudo apt install gobuster -y
Purpose:
Gobuster is used to enumerate directories and files exposed by web applications.
ex: http://10.0.2.99/ ↓ Gobuster ↓ /admin /login /uploads /backup
Install Wordlists
Wordlists
sudo apt install wordlists -y
Purpose:
Gobuster needs a list of possible directory/file names to test.
The project uses:/usr/share/wordlists/dirb/common.txt
Then verify:
Check Nmap: nmap — version
Check Gobuster: gobuster — help
Check the wordlist: ls /usr/share/wordlists/dirb/common.txt
9. Install Python Dependencies
Python is the main automation/orchestration layer of this project.
First check Python:
python3 — version
Example:
Python 3.13.14
Check pip:
pip3 — version
Example:
pip 26.1.2
The project uses the OpenAI Python library to communicate with an OpenAI-compatible API interface provided by Groq.
Install it:
pip3 install openai — break-system-packages
Verify the installation:
python3 -c "import openai; print(openai.version)"
Example:
3.3.1
Why do we need the OpenAI Python library?
It provides the Python-side client used to make API requests.
The relationship is:
Python
↓
OpenAI Python Library
↓
Groq API
↓
AI Model
Important: Installing the OpenAI library does not mean that you are using OpenAI's AI model. In this project, the client library is being used to communicate with Groq's OpenAI-compatible API interface.
10. Configure the Groq API Key
The Python application needs authentication when communicating with the Groq API.
Create or obtain your API key from your Groq account, then set it as an environment variable:
export GROQ_API_KEY="YOUR_GROQ_API_KEY"
The Python program can retrieve it using:
os.getenv("GROQ_API_KEY")
What happens here?
Python
↓
Groq API request
↓
GROQ_API_KEY
↓
Authentication
↓
Groq verifies the key
↓
Request accepted
The API key should never be hard-coded into the Python source code or published in screenshots/GitHub.
11. Build pentest_ai.py
Now we create the main Python program:
nano pentest_ai.py
This file is the core of the automation.
The Python program is responsible for coordinating the complete workflow:
targets.txt
↓
Read target
↓
Run Nmap
↓
Run Nmap NSE
↓
Run Gobuster
↓
Read result files
↓
Prepare evidence
↓
Send evidence to Groq
↓
Receive AI analysis
↓
Generate HTML report
↓
Open Firefox
Source Code :
#!/usr/bin/env python3 import os import subprocess import shutil import html from pathlib import Path from datetime import datetime from openai import OpenAI
============================================================
AI PENTEST AUTOMATION
Authorized laboratory / training environments only
============================================================
TARGET_FILE = "targets.txt" NMAP_FILE = "nmap_results.txt" VULN_FILE = "vuln_results.txt" GOBUSTER_80_FILE = "gobuster_80.txt" GOBUSTER_8180_FILE = "gobuster_8180.txt" REPORT_FILE = "/home/kali/ai-pentest-lab/pentest_report.html" USER_REPORT_FILE = "/home/kali/pentest_report.html" MODEL = "openai/gpt-oss-120b" MAX_EVIDENCE_CHARS = 3000 MAX_OUTPUT_TOKENS = 3000
============================================================
Terminal formatting
============================================================
def banner(): print() print("=" * 70) print(" AI PENTEST AUTOMATION") print("=" * 70) print()
============================================================
File helpers
============================================================
def read_file(filename): path = Path(filename) if not path.exists(): print(f"[!] {filename} not found") return "" return path.read_text(errors="ignore") def write_file(filename, content): Path(filename).write_text(content, encoding="utf-8") def trim_text(text, max_chars): if len(text) <= max_chars: return text return text[:max_chars] + "\n…[evidence truncated]…"
============================================================
Run command
============================================================
def run_command(command, output_file): print() print("[+] Running:") print(" " + " ".join(command)) try: with open(output_file, "w", encoding="utf-8") as outfile: process = subprocess.run( command, stdout=outfile, stderr=subprocess.STDOUT, text=True ) if process.returncode != 0: print( f"[!] Command returned exit code " f"{process.returncode}" ) print(f"[+] Saved output to {output_file}") except Exception as e: print(f"[!] Error running command: {e}")
============================================================
Get target
============================================================
target = read_file(TARGET_FILE).strip() if not target: raise SystemExit( "[!] targets.txt is empty or missing" )
============================================================
API key
============================================================
api_key = os.getenv("GROQ_API_KEY") if not api_key: raise SystemExit( "GROQ_API_KEY is not set" )
============================================================
Start
============================================================
banner() print(f"[+] Target: {target}")
============================================================
1. Nmap service detection
============================================================
run_command( [ "nmap", "-sV", "-oN", NMAP_FILE, "-iL", TARGET_FILE ], NMAP_FILE )
============================================================
2. Nmap NSE vulnerability scan
============================================================
run_command( [ "nmap", "-sV", " — script", "vuln", "-iL", TARGET_FILE, "-oN", VULN_FILE ], VULN_FILE )
============================================================
3. Gobuster HTTP port 80
============================================================
run_command( [ "gobuster", "dir", "-u", f"http://{target}/", "-w", "/usr/share/wordlists/dirb/common.txt", "-o", GOBUSTER_80_FILE ], GOBUSTER_80_FILE )
============================================================
4. Gobuster HTTP port 8180
============================================================
run_command( [ "gobuster", "dir", "-u", f"http://{target}:8180/", "-w", "/usr/share/wordlists/dirb/common.txt", "-o", GOBUSTER_8180_FILE ], GOBUSTER_8180_FILE )
============================================================
Load evidence
============================================================
print() print("[+] Loading pentest evidence…") nmap_results = read_file(NMAP_FILE) vuln_results = read_file(VULN_FILE) gobuster_80 = read_file(GOBUSTER_80_FILE) gobuster_8180 = read_file(GOBUSTER_8180_FILE) print( f"[+] Nmap results: " f"{len(nmap_results)} characters" ) print( f"[+] NSE results: " f"{len(vuln_results)} characters" ) print( f"[+] Gobuster :80: " f"{len(gobuster_80)} characters" ) print( f"[+] Gobuster :8180: " f"{len(gobuster_8180)} characters" )
============================================================
Build AI evidence
============================================================
evidence = f""" TARGET — — — {target} NMAP SERVICE DETECTION — — — — — — — — — — — {nmap_results} GOBUSTER HTTP PORT 80 — — — — — — — — — — - {gobuster_80} GOBUSTER HTTP PORT 8180 — — — — — — — — — — — - {gobuster_8180} NMAP NSE VULNERABILITY RESULTS — — — — — — — — — — — — — — — {vuln_results} """ evidence = trim_text( evidence, MAX_EVIDENCE_CHARS ) print( f"[+] Evidence sent to Groq: " f"{len(evidence)} characters" )
============================================================
AI system prompt
============================================================
system_prompt = """ You are a cybersecurity penetration-testing assistant. The target is an AUTHORIZED laboratory/training machine. Analyze ONLY the evidence supplied by the user. Do NOT invent:
- vulnerabilities
- CVEs
- credentials
- exploit results
- successful compromises
- service versions
- authentication results CRITICAL EVIDENCE RULE: A service being open does NOT mean it was exploited. A version being old does NOT prove exploitation. An HTTP 200/301/302 response proves accessibility or redirection, but does NOT prove that the endpoint is vulnerable. A vulnerability should be classified as CONFIRMED only when the supplied evidence explicitly demonstrates it. Use these categories: CONFIRMED LIKELY POSSIBLE INFORMATIONAL For every finding include:
- Finding
- Severity
- Evidence
- Explanation
- Validation status Use the exact evidence where possible. Do not claim that default credentials work unless the supplied evidence demonstrates that they work. Do not claim root access unless the supplied evidence demonstrates root access. The assessment should be useful for an authorized lab exercise. Produce a COMPLETE report. Do not stop in the middle of a sentence. Use exactly these sections:
- Executive Summary
- Attack Surface
- Confirmed Findings
- Likely Findings
- Possible Findings
- Web Enumeration Findings
- Risk Prioritization
- Recommended Validation Steps
- Final Assessment At the end include: "End of Report" Keep the report concise enough to fit within the response limit. """
============================================================
AI user prompt
============================================================
user_prompt = f""" Analyze this authorized penetration-testing evidence. TARGET: {target} EVIDENCE: {evidence} Generate the complete penetration-test assessment now. """
============================================================
Groq client
============================================================
client = OpenAI( api_key=api_key, base_url="https://api.groq.com/openai/v1" )
============================================================
Send to AI
============================================================
print() print("[+] Sending evidence to Groq…") try: response = client.chat.completions.create( model=MODEL, messages=[ { "role": "system", "content": system_prompt }, { "role": "user", "content": user_prompt } ], max_tokens=MAX_OUTPUT_TOKENS, temperature=0.1 ) except Exception as e: print() print("[!] Groq API request failed:") print(e) raise SystemExit(1)
============================================================
Get AI report
============================================================
report = response.choices[0].message.content if not report: raise SystemExit( "[!] Groq returned an empty report" ) print() print( f"[+] AI report received: " f"{len(report)} characters" )
============================================================
Convert simple Markdown to HTML
============================================================
def markdown_to_html(text): lines = text.splitlines() output = [] in_table = False table_header_done = False for line in lines: stripped = line.strip() if not stripped: if in_table: output.append("") in_table = False table_header_done = False continue if stripped in [" — -", "", "___"]: if in_table: output.append("") in_table = False table_header_done = False output.append("
") continue if stripped.startswith("### "): if in_table: output.append("") in_table = False table_header_done = False heading = html.escape( stripped[4:] ) output.append( f"
{heading}
" ) continue if stripped.startswith("## "): if in_table: output.append("") in_table = False table_header_done = False heading = html.escape( stripped[3:] ) output.append( f"{heading}
" ) continue if stripped.startswith("# "): if in_table: output.append("") in_table = False table_header_done = False heading = html.escape( stripped[2:] ) output.append( f"{heading}
" ) continue if ( len(stripped) > 3 and stripped[0].isdigit() and ". " in stripped[:4] ): if in_table: output.append("") in_table = False table_header_done = False output.append( "" + html.escape(stripped) + "
" ) continue if stripped.startswith("|") and stripped.endswith("|"): cells = [ cell.strip() for cell in stripped.strip("|").split("|") ] if all( set(cell) <= set("-: ") for cell in cells ): continue if not in_table: output.append( "" ) in_table = True table_header_done = False tag = ( "th" if not table_header_done else "td" ) row = "" for cell in cells: cell_html = html.escape( cell ) row += ( f"<{tag}>" f"{cell_html}" f"</{tag}>" ) row += "" output.append(row) if not table_header_done: table_header_done = True continue if stripped.startswith(" "): output.append( "{paragraph}
" ) if in_table: output.append("============================================================
Create HTML
============================================================
generated_time = datetime.now().strftime( "%Y-%m-%d %H:%M:%S" ) report_html = markdown_to_html( report ) full_html = f"""
AI Penetration Test Report — {html.escape(target)} body {{ font-family: Arial, Helvetica, sans-serif; background: #f4f6f8; color: #222; margin: 0; padding: 0; line-height: 1.6; }} .container {{ max-width: 1200px; margin: 30px auto; background: white; padding: 40px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }} .header {{ border-bottom: 3px solid #222; padding-bottom: 20px; margin-bottom: 30px; }} .header h1 {{ margin-bottom: 5px; }} .meta {{ color: #666; font-size: 14px; }} h1 {{ color: #111; }} h2 {{ margin-top: 35px; padding-bottom: 8px; border-bottom: 1px solid #ddd; }} h3 {{ margin-top: 25px; }} table {{ width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 14px; }} th {{ background: #222; color: white; padding: 10px; border: 1px solid #ccc; text-align: left; }} td {{ padding: 10px; border: 1px solid #ccc; vertical-align: top; }} tr:nth-child(even) {{ background: #f7f7f7; }} li {{ margin-bottom: 8px; }} hr {{ border: 0; border-top: 1px solid #ddd; margin: 30px 0; }} .footer {{ margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #777; font-size: 13px; }}AI Penetration Test Report
source code :
pentest_ai.py is the main source code and automation file of this project. The user only needs to provide the authorized target IP address or domain name in targets.txt. After that, Python automatically handles the remaining process. It runs Nmap to scan the target and identify open ports, services, and versions, runs Nmap NSE vulnerability scripts to perform vulnerability checks, and uses Gobuster with a predefined wordlist to enumerate web directories and files. Python then collects the results from all these tools and prepares them as pentest evidence. This evidence is sent to the Groq API using the OpenAI Python library, where the selected AI model analyzes the collected information and generates security findings and report content. Finally, Python receives the AI response, creates an HTML penetration testing report, and opens the report in Firefox.
12. Make the Python File Executable
Run:
chmod +x pentest_ai.py
Here:
chmod
↓
Change file permissions
+x
↓
Add execute permission
It does not mean 777.
It simply adds the execute permission according to the applicable permission classes.
You can check:
ls -l pentest_ai.py
In one sentence:
The user provides an authorized target → Python orchestrates Nmap, Nmap NSE, and Gobuster → Python collects their results → the OpenAI Python library sends the prepared evidence to Groq → the Groq API authenticates the request using the API key → the AI model analyzes the evidence → Python receives the AI response → generates an HTML penetration-testing report → and opens it in Firefox.