A self-hosted pentest management workspace. Track engagements, run tools, auto-import findings, generate professional reports.
A self-hosted workspace for pentesters, red teamers, bug bounty hunters, and certification grinds (OSCP / OSEP / CRTP / PNPT / HTB). Run your tools from the UI, auto-import findings, track methodology phases, share results with clients, and generate a report when you're done — all from one place, on infrastructure you control.
No cloud. No SaaS. Your data stays on your server.
| Area | What's in there |
|---|---|
| Engagements |
Targets · open ports · PTES checklist (7 phases) · attack path tracker · credentials vault · timeline · time tracking · loot · archive + restore · .pcbundle export/import
|
| Findings | CVSS v3.1 · comments · evidence uploads · status workflow · CVE lookup · per-engagement import/export · 2400+ template library · bulk import from Nessus and Burp Suite XML · bulk operations (set severity / status / assignee · mark FP · delete) |
| Tools Hub | 90+ tools across 10 categories · host-aware availability detection · install hints · live output streaming · auto-import findings · job persistence across reloads |
| Web Scanner | TLS · security headers · cookies · CORS · HTTP methods · exposed files · tech fingerprint · HTML hygiene · scan diffing · SSRF guard · deep-scan mode |
| Reporting | DOCX + PDF · branded cover page (logo, colour, footer) · executive summary · technical report · per-engagement redact and section toggles |
| Client Portals | Token-based read-only links · optional password protection · optional expiry · view count tracking · share findings without giving clients access to the app |
| Exam Mode | OSCP · OSEP · OSED · CRTP · PNPT · CPTS · Custom · live countdown in navbar · points tracker · screenshot slots · exam-style DOCX report |
| Team & Auth | Roles (viewer / operator / admin / owner) · invite links with email delivery · TOTP MFA · password reset via email · audit log · team branding settings |
| Terminal Logging |
Personal API tokens · pipe any command output into an engagement session · ANSI viewer · pclog bash helper
|
| Workflow Playbooks | Sequential multi-step scan pipelines · 5 built-in playbooks (External Recon, Web App, Network Discovery, AD/SMB Enum, TLS Audit) · live step-by-step status page · cancel support · custom playbooks via CRUD |
| Scheduled Scans | Per-target recurring scans · configurable tool + interval · background daemon scheduler (60 s tick) · results auto-imported into engagement |
| Webhooks | Slack · Discord · Teams · Generic JSON · fires on auto-import and manual findings · delivery log + test-fire button · SSRF-guarded URL validation |
| REST API |
GET /api/v1/engagements · GET /api/v1/engagements/<id>/findings · paginated · severity + status filters · Bearer token auth
|
| Utilities | Hash identifier · Base64 codec · command renderer · scratchpad with auto-parsing · Markdown notes with autosave · Obsidian vault import |
git clone https://github.com/Poellie01/PentestCompanion.git
cd PentestCompanion
cp .env.example .env
# Generate a real SECRET_KEY
python3 -c "import secrets; print(secrets.token_hex(32))" \
| xargs -I {} sed -i 's/^SECRET_KEY=$/SECRET_KEY={}/' .env
# Set ADMIN_PASSWORD (and SMTP/Resend if you want email)
$EDITOR .env
docker compose up -d
docker compose logs -f appFirst run bootstraps an admin account and prints the credentials:
============================================================
Bootstrapped admin account.
username: admin
password: changeme
!! CHANGE THIS PASSWORD or set ADMIN_PASSWORD in .env
============================================================
Hit http://localhost:5000, sign in, change your password under Account → Update Password.
git clone https://github.com/Poellie01/PentestCompanion.git
cd PentestCompanion
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python app.pyFull engagement management — targets, ports, credentials, attack steps, PTES checklist, timeline, and time tracking in one view. Export any engagement as a .pcbundle and restore it on any Pentest Companion instance.
CVSS v3.1 scoring, evidence uploads, CVE lookup, remediation tracking, and a 40+ template library. Import findings from Nessus (.nessus) and Burp Suite (XML export) in one click.
The tools hub discovers what's installed on the host and gives you a point-and-click interface for 50+ common tools. Running Pentest Companion on Kali Linux gives you the full set out of the box.
Categories: Network · Web · AD/Windows · Impacket · Password Attacks · DNS · SSL/TLS · OSINT · Linux Enumeration · Custom
| Category | Tools |
|---|---|
| Network | nmap (quick / full / vuln), masscan, netcat |
| Web | nikto, gobuster (dir/dns/vhost), ffuf, whatweb, wafw00f, wpscan, sqlmap, feroxbuster, nuclei |
| AD / Windows | enum4linux-ng, smbmap, smbclient, netexec (SMB/LDAP/WinRM/RDP/MSSQL), ldapsearch, rpcclient, kerbrute |
| Impacket | secretsdump, GetNPUsers, GetUserSPNs, psexec, wmiexec, getTGT |
| Password | hydra, hashcat, john |
| DNS | dnsenum, dnsrecon, fierce, amass, subfinder |
| SSL/TLS | sslscan, testssl.sh |
| OSINT | theHarvester, searchsploit |
| Linux | linpeas, pspy |
| Custom | free-form shell command runner |
When you add a target to an engagement, expand Auto-Scan in the modal and tick the tools you want. Each selected tool runs in the background — findings land in the engagement automatically when the job completes.
Passive scanner — fires a small, fixed set of HTTP requests.
| Category | Checks |
|---|---|
| TLS | Cert expiry, self-signed, TLS 1.0/1.1, HTTP→HTTPS redirect |
| Security headers | HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy |
| Cookies | Secure / HttpOnly / SameSite on every Set-Cookie |
| CORS | Wildcard, origin reflection, null origin |
| HTTP methods | TRACE / TRACK / PUT / DELETE / CONNECT |
| Exposed files | .git/config, .env, .DS_Store, phpinfo.php, server-status, and more |
| HTML hygiene | Mixed content, password autocomplete, forms missing CSRF tokens |
| Tech fingerprint | nginx, Apache, IIS, Cloudflare, PHP, WordPress, React, Vue, Angular, and more |
Deep scan adds directory enumeration and JS endpoint extraction. Scan diffing lets you compare two scans side-by-side. Auto-promote pushes scan findings into an engagement in one click.
Pipe any command output into an engagement session and replay it later with full ANSI colour.
Step 1 — get a token: Account → API Tokens → New Token
Step 2 — add to your shell config:
PCLOG_TOKEN="pcsk_your_token_here"
PCLOG_BASE="http://localhost:5000"
pclog() {
local eid=$1; shift
local name="${*:-$(date +%H:%M:%S)}"
local sid
sid=$(curl -sf -X POST "$PCLOG_BASE/api/v1/terminal/start" \
-H "Authorization: Bearer $PCLOG_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"engagement_id\":$eid,\"name\":\"$name\"}" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['session_id'])")
while IFS= read -r line; do
printf '%s\n' "$line"
printf '%s\n' "$line" | curl -sf -X POST "$PCLOG_BASE/api/v1/terminal/append/$sid" \
-H "Authorization: Bearer $PCLOG_TOKEN" \
-H "Content-Type: application/octet-stream" --data-binary @- > /dev/null
done
curl -sf -X POST "$PCLOG_BASE/api/v1/terminal/close/$sid" \
-H "Authorization: Bearer $PCLOG_TOKEN" > /dev/null
}Step 3 — use it:
nmap -sV 10.10.10.1 | pclog 42 "nmap initial"
gobuster dir -u http://10.10.10.1 -w /usr/share/wordlists/dirb/common.txt | pclog 42 "gobuster web"Run a sequenced chain of tools against a target in one click. Each step waits for the previous one to finish before launching.
Built-in playbooks:
| Playbook | Steps |
|---|---|
| External Recon | nmap → theHarvester → amass → whatweb |
| Web App | nikto → gobuster → ffuf → sqlmap |
| Network Discovery | masscan → nmap (full) → enum4linux-ng |
| AD / SMB Enum | netexec SMB → smbmap → ldapsearch → kerbrute |
| TLS Audit | sslscan → testssl.sh |
Navigate to Playbooks in the nav bar, pick a playbook, select a target, and watch each step advance in real time. You can cancel mid-run and create custom playbooks through the same UI.
Set a tool to run against a target on a recurring schedule — every hour, every 6 hours, daily, or weekly. A background daemon claims and runs due jobs every 60 seconds; findings land in the engagement automatically.
Target page → Scheduled Scans → Add Schedule → pick tool + interval
Get notified in Slack, Discord, or Teams whenever a finding is created — either by an auto-import job or manually.
Supported formats: Slack Block Kit · Discord embeds · Teams MessageCard · Generic JSON
Team Settings → Webhooks → New Webhook → paste URL → Test
Each delivery is logged with status code and response body. Webhook URLs are validated against the SSRF block-list before saving.
Select one or more findings with the row checkboxes (or Select All), then use the sticky bulk action bar to:
- Set severity, status, or assignee across all selected findings in one click
- Mark selected findings as False Positive
- Delete selected findings
Two read endpoints are available for external tooling and integrations. All requests require a Bearer token (create one under Team Settings → API Tokens).
| Endpoint | Description |
|---|---|
GET /api/v1/engagements |
List all engagements for your team |
GET /api/v1/engagements/<id>/findings |
Paginated findings; filter by severity and status |
curl -H "Authorization: Bearer pcsk_yourtoken" \
http://localhost:5000/api/v1/engagements/1/findings?severity=critical&page=1Export any engagement as a .pcbundle file (a versioned ZIP containing all data and evidence files). Import it on any Pentest Companion instance — useful for sharing engagements between team members, archiving, or moving between instances.
Engagement → Export Bundle → client-engagement.pcbundle
↓
Dashboard → Import Bundle
(drag-and-drop, live preview)
Full format reference at /bundle/help when running the app.
Share findings with clients without giving them access to the app. Each portal link is token-based, optionally password-protected, and optionally set to expire.
Engagement → #portal → New Portal Link → send link to client
Clients see: finding title, severity, description, remediation, CVSS score, and CVE ID. Nothing internal (credentials, attack steps, notes) is exposed.
Each target gets a structured checklist organised around PTES pentest phases:
| Phase | Coverage |
|---|---|
| Enumeration | Port scan, service version, OS detection, DNS, SNMP, SMB shares, LDAP |
| Initial Access | Exploit known CVEs, password spray, phishing, default creds, SQLi, web shells |
| Privilege Escalation | SUID/GUID, sudo misconfig, kernel exploits, token impersonation, ACL abuse |
| Lateral Movement | Pass-the-hash, Pass-the-ticket, RDP, WMI, PSExec, SSH tunnelling |
| Data Exfiltration | Sensitive file locations, credential files, DB dump, AD secrets |
| Persistence | Cron jobs, startup items, registry run keys, golden ticket, new admin accounts |
| Reporting | Screenshot collection, timeline review, cleanup verification |
Supports: OSCP · OSEP · OSED · CRTP · PNPT · CPTS · Custom
- Live countdown baked into the navbar
- Per-machine tracking: type, points, flags, and screenshot slots
- Pass/fail badge updates in real time as flags come in
- Generate exam-style DOCX/PDF report when done
| Variable | Default | Purpose |
|---|---|---|
SECRET_KEY |
auto-generated | Session signing key — set explicitly in production |
ADMIN_PASSWORD |
changeme |
Bootstrapped admin password (first run only) |
ADMIN_EMAIL |
admin@example.com |
Bootstrapped admin email |
APP_BASE_URL |
— | Public URL of your instance — required for correct links in emails |
ALLOW_REGISTRATION |
1 |
Set to 0 for invite-only |
FORCE_HTTPS |
0 |
Adds Secure cookie flag + HSTS header — set to 1 in production |
MAX_UPLOAD_MB |
25 |
Evidence upload size cap |
DATABASE_PATH |
pentest.db |
SQLite file path |
UPLOAD_FOLDER |
static/uploads |
Evidence files and logos |
HOST_PORT |
5000 |
Host-side port for Docker Compose |
GUNICORN_WORKERS |
4 |
Gunicorn worker count |
ALLOW_INTERNAL_SCANS |
0 |
Allow scanning RFC1918 / loopback targets |
Without email config, reset links are printed to the server log — fine for local use.
| Variable | Purpose |
|---|---|
RESEND_API_KEY |
Resend API key (recommended — sign up at resend.com) |
SMTP_HOST |
Generic SMTP server hostname |
SMTP_PORT |
SMTP port (default 587) |
SMTP_USER |
SMTP username |
SMTP_PASS |
SMTP password |
SMTP_FROM |
From address |
SMTP_TLS |
Set to 0 to disable STARTTLS |
| Control | Implementation |
|---|---|
| Sessions | HttpOnly + SameSite=Lax cookies; FORCE_HTTPS=1 adds Secure |
| Passwords | PBKDF2-SHA256 via werkzeug.security |
| MFA | TOTP (RFC 6238) via pyotp — per-user, optional |
| Password reset | Single-use time-limited tokens; username-enumeration-safe response |
| CSRF | Flask-WTF on every form; AJAX auto-includes token via meta tag |
| Cross-team isolation | Every <int:id> route goes through a require_* helper that 404s on cross-team access |
| Evidence path traversal | Paths looked up in DB and served only when engagement belongs to your team |
| Scanner SSRF | Blocks loopback, link-local, cloud metadata (169.254.169.254), and RFC1918 by default |
| API tokens | pcsk_ prefix, SHA-256 hashed at rest, per-token revocable |
| Audit log | Security-relevant events logged to DB (login, role changes, member removal, portal creation) |
app.py # Flask application — core routes, models, init_db
config.py # All env config + shared constants
database.py # DB layer: get_db(), init_db(), migrations, CVE sync
helpers.py # Auth guards, row fetchers, audit(), token_required
scheduler.py # Consolidated kali + web-scanner scheduler daemon
scanner.py # Web security scanner (pure stdlib)
reporting.py # Report helpers: MITRE map, risk score, diff, roadmap
commands.py # Renderable pentest command templates
requirements.txt
Dockerfile
docker-compose.yml
.env.example
blueprints/ # Route blueprints (refactor in progress)
auth.py # 20 auth routes
team.py # 32 team + webhook + API-token routes
reports.py # 23 report + bundle + client-portal routes
scanner.py # Web scanner + terminal + playbooks + scheduled scans
engagements.py # Engagements, targets, findings, sub-resources
tools/ # Kali tool integration package
manifest.py # 90+ tool definitions
profiles.py # ScanProfile dataclass + build/parse logic
generic_runner.py # subprocess + SSE streaming + auto-import
generic_parser.py # Universal finding extractor (regex + JSON)
base.py # ToolJobRunner ABC + job persistence
playbook_engine.py # Sequential multi-step playbook executor
webhooks.py # Slack / Discord / Teams / JSON notifier
trigger_engine.py # Finding triggers + FP triage
auto_orchestrator.py # Auto-scan orchestration
auto_discover.py # Host/service auto-discovery
templates/ # Jinja2 templates
static/
style.css # Single stylesheet
app.js
tests/ # 258 tests
conftest.py # App fixtures, auth helpers
test_auth.py # Login, registration, SSRF guard
test_routes.py # Route smoke tests
test_leakage.py # Cross-team isolation on every <int:id> endpoint
test_team.py # Role enforcement, invite flow, member management
test_security.py # Security controls
test_reporting.py # Reporting helpers
test_webhooks.py # Webhook delivery + formatting
test_playbook_engine.py # Playbook executor
test_trigger_engine.py # Finding triggers
test_generic_parser.py # Universal parser (97% coverage)
test_auto_orchestrator.py # Auto-orchestration (73% coverage)
pip install pytest
pytest # all tests
pytest tests/test_leakage.py # cross-team isolation
pytest -v # verboseLicensed under the GNU Affero General Public License v3.0.
For commercial licensing (white-label, proprietary redistribution, or enterprise use) contact: info@ceretrix.net
Made for pentesters, by a pentester. Have fun.






