
Metatron Pentest Assistant
- 584 installs
- 66 repo stars
- Updated July 9, 2026
- aradotso/trending-skills
metatron-pentest-assistant is a Claude Code skill that runs fully local AI-assisted penetration tests and vulnerability scans using metatron-qwen via Ollama on Parrot OS Linux for developers who need automated pentesting
About
METATRON is a fully local CLI-based AI penetration testing assistant designed for solo builders and indie developers who need to run professional-grade security scans without sending data to any cloud service. It combines industry-standard reconnaissance tools with a locally hosted fine-tuned LLM that interprets results, suggests exploits, and recommends fixes. All findings are stored in a MariaDB database for historical tracking, trend analysis, and report generation. The skill runs on Parrot OS Linux, uses Ollama to power its metatron-qwen model, and includes modules for database management, tool orchestration, DuckDuckGo-based CVE lookup, and extensible agentic workflows. Perfect for developers who want to integrate automated security testing into their local development and pre-launch routines.
- Orchestrates local recon tools including nmap, nikto, whois, whatweb, dig and curl
- Feeds scan results into a fine-tuned local LLM (metatron-qwen via Ollama) for agentic analysis
- Stores complete scan history, vulnerabilities, and remediation steps in MariaDB
- Exports vulnerability reports as PDF or HTML with no cloud or API keys required
- Supports adding custom recon tools and querying historical scan data
Metatron Pentest Assistant by the numbers
- 584 all-time installs (skills.sh)
- +9 installs in the week ending Jun 27, 2026 (Skillselion tracking)
- Ranked #484 of 2,209 Security skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Jul 19, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aradotso/trending-skills --skill metatron-pentest-assistantAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 584 |
|---|---|
| repo stars | ★ 66 |
| Security audit | 0 / 3 scanners passed |
| Last updated | July 9, 2026 |
| Repository | aradotso/trending-skills ↗ |
How do you run local AI penetration tests on Parrot OS?
Run fully-local AI-assisted penetration tests and vulnerability scans on their own applications or infrastructure.
Who is it for?
Security engineers on Parrot OS who want Ollama-powered automated pentests and local vulnerability reports on applications they own.
Skip if: Developers who cannot run Parrot OS with Ollama and MariaDB or who need certified third-party penetration testing for compliance sign-off.
When should I use this skill?
The user asks to set up METATRON, run AI-assisted penetration testing, add recon scans, export vulnerability reports, or troubleshoot the local model or scan database.
What you get
Configured METATRON CLI environment, completed recon scans, MariaDB scan history records, and exported vulnerability reports.
- vulnerability reports
- recon scan results
- MariaDB scan history records
Files
METATRON Penetration Testing Assistant
Skill by ara.so — Daily 2026 Skills collection.
METATRON is a CLI-based AI penetration testing assistant that runs entirely locally — no cloud, no API keys. It orchestrates recon tools (nmap, whois, whatweb, curl, dig, nikto), feeds results to a locally running fine-tuned LLM (metatron-qwen via Ollama), and stores all findings in MariaDB with full scan history, vulnerability tracking, and PDF/HTML export.
---
Architecture Overview
metatron.py ← CLI entry point, main menu, scan orchestration
db.py ← MariaDB CRUD (history, vulns, fixes, exploits, summary)
tools.py ← Recon tool runners (nmap, whois, whatweb, curl, dig, nikto)
llm.py ← Ollama interface, agentic loop, AI tool dispatch
search.py ← DuckDuckGo search + CVE lookup (no API key)
Modelfile ← Custom metatron-qwen model configDatabase spine: every scan creates a sl_no in history; all other tables link via sl_no.
---
Installation
1. Clone and set up Python environment
git clone https://github.com/sooryathejas/METATRON.git
cd METATRON
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt2. Install system recon tools
sudo apt install nmap whois whatweb curl dnsutils nikto3. Install Ollama and pull base model
curl -fsSL https://ollama.com/install.sh | sh
# 8GB+ RAM:
ollama pull huihui_ai/qwen3.5-abliterated:9b
# <8GB RAM — use 4b and edit Modelfile FROM line accordingly:
ollama pull huihui_ai/qwen3.5-abliterated:4b4. Build the custom metatron-qwen model
ollama create metatron-qwen -f Modelfile
ollama list # verify metatron-qwen appearsModelfile (the repo ships this — key parameters):
FROM huihui_ai/qwen3.5-abliterated:9b
PARAMETER num_ctx 16384
PARAMETER temperature 0.7
PARAMETER top_k 10
PARAMETER top_p 0.9To use 4b instead, edit Modelfile:
FROM huihui_ai/qwen3.5-abliterated:4bThen rebuild: ollama create metatron-qwen -f Modelfile
5. Set up MariaDB
sudo systemctl start mariadb
sudo systemctl enable mariadb
mysql -u rootCREATE DATABASE metatron;
CREATE USER 'metatron'@'localhost' IDENTIFIED BY '123';
GRANT ALL PRIVILEGES ON metatron.* TO 'metatron'@'localhost';
FLUSH PRIVILEGES;
EXIT;Create all tables:
mysql -u metatron -p123 metatron < schema.sqlOr manually (paste from README schema block). The 5 tables:
history— one row per scan session (spine)vulnerabilities— findings per sessionfixes— remediation per vulnerabilityexploits_attempted— exploit attempts per sessionsummary— raw scan + full AI analysis dump
---
Running METATRON
METATRON requires two terminals:
Terminal 1 — Load model into memory:
ollama run metatron-qwen
# Wait for >>> prompt before proceedingTerminal 2 — Launch the assistant:
cd ~/METATRON
source venv/bin/activate
python metatron.pyMain Menu Flow
[1] New Scan → enter target IP/domain → select tools → AI analyzes → saved to DB
[2] View History → browse past scans → view/edit/delete/export
[3] ExitNew Scan — Tool Selection
[1] nmap
[2] whois
[3] whatweb
[4] curl headers
[5] dig DNS
[6] nikto
[a] Run all (except nikto)
[n] Run all + nikto (slow, thorough)Exporting Reports
From View History → select scan → export:
PDF— professional vulnerability reportHTML— browser-viewable report
---
Code Examples
Programmatically run a scan and save to DB (db.py patterns)
import mysql.connector
def get_db_connection():
return mysql.connector.connect(
host="localhost",
user="metatron",
password="123",
database="metatron"
)
def create_scan_session(target: str) -> int:
"""Create a new history entry, return sl_no."""
from datetime import datetime
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
"INSERT INTO history (target, scan_date, status) VALUES (%s, %s, %s)",
(target, datetime.now(), "active")
)
conn.commit()
sl_no = cursor.lastrowid
cursor.close()
conn.close()
return sl_no
def save_vulnerability(sl_no: int, vuln_name: str, severity: str,
port: str, service: str, description: str) -> int:
"""Save a vulnerability finding, return vuln id."""
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
"""INSERT INTO vulnerabilities
(sl_no, vuln_name, severity, port, service, description)
VALUES (%s, %s, %s, %s, %s, %s)""",
(sl_no, vuln_name, severity, port, service, description)
)
conn.commit()
vuln_id = cursor.lastrowid
cursor.close()
conn.close()
return vuln_id
def save_fix(sl_no: int, vuln_id: int, fix_text: str, source: str = "AI"):
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
"INSERT INTO fixes (sl_no, vuln_id, fix_text, source) VALUES (%s, %s, %s, %s)",
(sl_no, vuln_id, fix_text, source)
)
conn.commit()
cursor.close()
conn.close()
def save_summary(sl_no: int, raw_scan: str, ai_analysis: str, risk_level: str):
from datetime import datetime
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
"""INSERT INTO summary (sl_no, raw_scan, ai_analysis, risk_level, generated_at)
VALUES (%s, %s, %s, %s, %s)""",
(sl_no, raw_scan, ai_analysis, risk_level, datetime.now())
)
conn.commit()
cursor.close()
conn.close()
def get_scan_history():
"""Retrieve all scan sessions."""
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM history ORDER BY scan_date DESC")
rows = cursor.fetchall()
cursor.close()
conn.close()
return rows
def get_vulnerabilities_for_scan(sl_no: int):
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute(
"SELECT * FROM vulnerabilities WHERE sl_no = %s", (sl_no,)
)
rows = cursor.fetchall()
cursor.close()
conn.close()
return rowsRunning recon tools (tools.py patterns)
import subprocess
def run_nmap(target: str) -> str:
"""Run nmap service/version scan."""
result = subprocess.run(
["nmap", "-sV", "-sC", "-T4", target],
capture_output=True, text=True, timeout=120
)
return result.stdout + result.stderr
def run_whois(target: str) -> str:
result = subprocess.run(
["whois", target],
capture_output=True, text=True, timeout=30
)
return result.stdout
def run_whatweb(target: str) -> str:
result = subprocess.run(
["whatweb", "-a", "3", target],
capture_output=True, text=True, timeout=60
)
return result.stdout
def run_curl_headers(target: str) -> str:
result = subprocess.run(
["curl", "-I", "-L", "--max-time", "15", target],
capture_output=True, text=True, timeout=20
)
return result.stdout
def run_dig(target: str) -> str:
result = subprocess.run(
["dig", target, "ANY"],
capture_output=True, text=True, timeout=15
)
return result.stdout
def run_nikto(target: str) -> str:
"""Slow but thorough web scanner."""
result = subprocess.run(
["nikto", "-h", target],
capture_output=True, text=True, timeout=300
)
return result.stdout
def run_selected_tools(target: str, selections: list) -> dict:
"""
selections: list of tool names, e.g. ['nmap', 'whois', 'dig']
Returns dict of {tool_name: output}
"""
tool_map = {
'nmap': run_nmap,
'whois': run_whois,
'whatweb': run_whatweb,
'curl': run_curl_headers,
'dig': run_dig,
'nikto': run_nikto,
}
results = {}
for tool in selections:
if tool in tool_map:
print(f"[*] Running {tool} on {target}...")
try:
results[tool] = tool_map[tool](target)
except subprocess.TimeoutExpired:
results[tool] = f"[TIMEOUT] {tool} timed out"
except Exception as e:
results[tool] = f"[ERROR] {tool}: {e}"
return resultsQuerying Ollama LLM (llm.py patterns)
import requests
import json
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "metatron-qwen"
def query_llm(prompt: str, stream: bool = True) -> str:
"""Send prompt to metatron-qwen, return full response."""
payload = {
"model": MODEL_NAME,
"prompt": prompt,
"stream": stream
}
response = requests.post(OLLAMA_URL, json=payload, stream=stream)
if not stream:
return response.json().get("response", "")
full_response = ""
for line in response.iter_lines():
if line:
chunk = json.loads(line)
token = chunk.get("response", "")
print(token, end="", flush=True)
full_response += token
if chunk.get("done"):
break
print()
return full_response
def build_pentest_prompt(target: str, scan_results: dict) -> str:
"""Build the analysis prompt from scan results."""
combined = "\n\n".join(
f"=== {tool.upper()} ===\n{output}"
for tool, output in scan_results.items()
)
return f"""You are an expert penetration tester analyzing scan results for: {target}
SCAN RESULTS:
{combined}
Provide a structured analysis covering:
1. VULNERABILITIES FOUND — name, severity (Critical/High/Medium/Low), port, service, description
2. EXPLOIT SUGGESTIONS — specific tools or techniques for each vulnerability
3. RECOMMENDED FIXES — actionable remediation steps
4. OVERALL RISK LEVEL — Critical / High / Medium / Low
Format vulnerabilities as:
VULN: <name> | SEVERITY: <level> | PORT: <port> | SERVICE: <service>
DESC: <description>
FIX: <remediation>
"""
def analyze_target(target: str, scan_results: dict) -> str:
prompt = build_pentest_prompt(target, scan_results)
print("\n[🤖] metatron-qwen analyzing...\n")
return query_llm(prompt)DuckDuckGo search and CVE lookup (search.py patterns)
from duckduckgo_search import DDGS
def search_exploits(query: str, max_results: int = 5) -> list:
"""Search DuckDuckGo for exploit info — no API key needed."""
with DDGS() as ddgs:
results = list(ddgs.text(query, max_results=max_results))
return results
def lookup_cve(cve_id: str) -> list:
"""Look up a CVE identifier."""
query = f"{cve_id} vulnerability exploit details"
return search_exploits(query)
def search_service_vulns(service: str, version: str) -> list:
query = f"{service} {version} known vulnerabilities CVE exploit"
return search_exploits(query)
# Usage example:
# results = lookup_cve("CVE-2021-44228")
# results = search_service_vulns("Apache", "2.4.49")Full scan pipeline (end-to-end)
from tools import run_selected_tools
from llm import analyze_target
from db import (create_scan_session, save_vulnerability,
save_fix, save_summary)
def run_full_scan(target: str, tools: list = None):
if tools is None:
tools = ['nmap', 'whois', 'whatweb', 'curl', 'dig']
# 1. Create DB session
sl_no = create_scan_session(target)
print(f"[+] Scan session #{sl_no} created for {target}")
# 2. Run recon
scan_results = run_selected_tools(target, tools)
raw_scan = "\n\n".join(f"{k}:\n{v}" for k, v in scan_results.items())
# 3. AI analysis
ai_output = analyze_target(target, scan_results)
# 4. Parse and save (simplified — real parser in llm.py)
# Save summary
save_summary(sl_no, raw_scan, ai_output, risk_level="High")
print(f"\n[✓] Results saved to database (sl_no={sl_no})")
return sl_no, ai_output
# Run it:
# sl_no, analysis = run_full_scan("192.168.1.1", ['nmap', 'whois'])---
Common Patterns
Check if Ollama model is running before scan
import requests
def check_ollama_ready(model: str = "metatron-qwen") -> bool:
try:
resp = requests.get("http://localhost:11434/api/tags", timeout=5)
models = [m["name"] for m in resp.json().get("models", [])]
return any(model in m for m in models)
except Exception:
return False
if not check_ollama_ready():
print("[!] metatron-qwen not found. Run: ollama run metatron-qwen")
exit(1)Query scan history
from db import get_db_connection
def get_full_scan_report(sl_no: int) -> dict:
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM history WHERE sl_no = %s", (sl_no,))
history = cursor.fetchone()
cursor.execute("SELECT * FROM vulnerabilities WHERE sl_no = %s", (sl_no,))
vulns = cursor.fetchall()
cursor.execute("SELECT * FROM summary WHERE sl_no = %s", (sl_no,))
summary = cursor.fetchone()
cursor.close()
conn.close()
return {"history": history, "vulnerabilities": vulns, "summary": summary}Add a custom recon tool
# In tools.py — add your tool function:
def run_gobuster(target: str, wordlist: str = "/usr/share/wordlists/dirb/common.txt") -> str:
result = subprocess.run(
["gobuster", "dir", "-u", f"http://{target}", "-w", wordlist],
capture_output=True, text=True, timeout=180
)
return result.stdout
# Register it in the tool_map in run_selected_tools():
tool_map['gobuster'] = run_gobuster---
Troubleshooting
metatron-qwen not found / connection refused
# Terminal 1: ensure model is loaded
ollama run metatron-qwen
# Should show >>> prompt
# Verify Ollama API is reachable
curl http://localhost:11434/api/tagsOut of memory when running 9b model
# Switch to 4b: edit Modelfile first line:
# FROM huihui_ai/qwen3.5-abliterated:4b
ollama create metatron-qwen -f ModelfileMariaDB connection error
sudo systemctl status mariadb
sudo systemctl start mariadb
# Verify credentials work:
mysql -u metatron -p123 metatron -e "SHOW TABLES;"mysql.connector not found
source venv/bin/activate
pip install mysql-connector-pythonnmap requires root for SYN scan
sudo nmap -sV -sC -T4 <target>
# Or use TCP connect scan (no root needed):
nmap -sT -sV <target>Nikto timeout
Nikto is slow by design. Either use [a] (all without nikto) or increase the subprocess timeout in tools.py:
result = subprocess.run(["nikto", "-h", target],
capture_output=True, text=True,
timeout=600) # 10 minutesSlow AI responses
The 9b model needs time to load. If response is slow after the first query, it's still loading. Subsequent queries will be faster. Ensure no other GPU/memory-heavy processes are running.
---
Configuration Reference
| Setting | Location | Default | Notes |
|---|---|---|---|
| DB host | db.py | localhost | Change for remote DB |
| DB user | db.py | metatron | Match SQL user created |
| DB password | db.py | 123 | Change in production |
| DB name | db.py | metatron | |
| Ollama URL | llm.py | http://localhost:11434 | |
| Model name | llm.py | metatron-qwen | Must match ollama list |
| Context window | Modelfile | 16384 | Increase for large scans |
| Temperature | Modelfile | 0.7 | Lower = more deterministic |
Security note: For production use, replace the hardcoded DB password with an environment variable: os.environ.get("METATRON_DB_PASSWORD", "123")---
Legal Disclaimer
METATRON is for educational purposes and authorized penetration testing only. Only scan systems you own or have explicit written permission to test. Unauthorized scanning is illegal.
Related skills
How it compares
Choose metatron-pentest-assistant over generic security checklists when you need a local Ollama-driven pentest CLI with MariaDB scan history on Parrot OS.
FAQ
What LLM does metatron-pentest-assistant use?
metatron-pentest-assistant uses metatron-qwen served locally through Ollama on Parrot OS Linux. The skill guides Ollama configuration and troubleshooting so recon scans and vulnerability analysis stay on-machine without cloud LLM calls.
Where does METATRON store scan history?
METATRON stores penetration test and recon scan history in a MariaDB database configured during setup. metatron-pentest-assistant includes steps to query that history and troubleshoot database connection issues when scans fail to persist.
Can METATRON use custom recon tools?
metatron-pentest-assistant documents how to extend METATRON with custom recon tools beyond the default modules. Developers add new scan types, run them through the CLI assistant, and export resulting vulnerability reports from the same workflow.
Is Metatron Pentest Assistant safe to install?
skills.sh reports 0 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.