PwnReport is a lightweight command-line tool for turning penetration testing results into a consistent, client-readable security assessment report.
It is designed for security consultants, penetration testers, and developers who already have assessment notes or findings and need a simple way to format, validate, and publish them. PwnReport keeps the source data structured in JSON and produces an offline HTML report with a professional dark theme.
PwnReport is a reporting tool, not a vulnerability scanner. It does not scan targets, exploit vulnerabilities, collect credentials, or replace tools such as Nmap, Burp Suite, Nessus, Nuclei, or Metasploit. Those tools can remain in the assessment workflow while PwnReport becomes the final reporting layer.
The original v0.1 foundation remains intentionally small:
init workspace -> edit report.json -> build report.html
It uses only the Python standard library and generates a self-contained HTML report that can be opened offline. The generated HTML includes a print stylesheet, so it can also be saved as PDF from a browser without adding a PDF library to the project.
PwnReport provides a small, predictable reporting pipeline:
- Create a report workspace with
pwnreport init. - Store engagement information in
report.json. - Add findings manually or normalize scanner exports through importers.
- Inspect findings and trace imported results back to preserved source files.
- Validate required fields, severity values, and unique finding IDs.
- Sort findings by severity.
- Build a self-contained HTML report with:
- Cover page
- Engagement information
- Assessment scope
- Executive summary
- Finding severity summary
- Finding descriptions, impact, evidence, and remediation
This approach is useful when the priority is a stable report format rather than a large platform. The JSON file remains easy to review in Git, generate from another script, or enrich through scanner importers.
The v0.4 release does not include a web interface, database, authentication, native PDF generation, report templates, or collaboration features. PwnReport imports scanner results but does not perform scanning or exploitation itself.
- Python 3.9 or newer
- No runtime dependencies
From the repository root:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .
pwnreport init demo-report
pwnreport finding add demo-report/report.json
pwnreport import nuclei demo-report/report.json nuclei-results.jsonl
pwnreport validate demo-report/report.json
pwnreport build demo-report/report.jsonOpen demo-report/output/report.html in a browser. The generated report also
includes a print stylesheet, so the browser's print dialog can be used to save
it as PDF without a PDF dependency.
Without installing the package, use the module directly:
PYTHONPATH=src python3 -m pwnreport --help
PYTHONPATH=src python3 -m pwnreport init demo-report
PYTHONPATH=src python3 -m pwnreport finding add demo-report/report.json
PYTHONPATH=src python3 -m pwnreport validate demo-report/report.json
PYTHONPATH=src python3 -m pwnreport build demo-report/report.jsonpwnreport --version
pwnreport init <directory>
pwnreport validate <report.json>
pwnreport finding add <report.json>
pwnreport finding list <report.json>
pwnreport finding show <report.json> <finding-id>
pwnreport import nuclei <report.json> <source.jsonl>
pwnreport import burp <report.json> <source.xml>
pwnreport import nmap <report.json> <source.xml>
pwnreport import nessus <report.json> <source.nessus>
pwnreport import custom <report.json> <source.json>
pwnreport build <report.json>
pwnreport build <report.json> --format all
pwnreport build <report.json> --format pdf --template executive
pwnreport build <report.json> --format markdown --theme light
pwnreport build <report.json> --format html --output custom.html
pwnreport library search [query]
pwnreport library show <lib-id>
pwnreport library save <report.json> <finding-id>
pwnreport library import <report.json> <lib-id> --affected-asset <asset>
pwnreport project list
pwnreport ui [--port 8080]init creates:
<directory>/
├── report.json
└── output/
The command never overwrites an existing report.json.
Run finding add without field flags to use the interactive prompts:
pwnreport finding add demo-report/report.jsonFor scripts and repeatable automation, provide all fields as flags:
pwnreport finding add demo-report/report.json \
--title "Missing Content Security Policy" \
--severity high \
--affected-asset "https://app.example.com" \
--description "The application does not return a CSP header." \
--impact "Client-side injection can have a wider impact." \
--evidence "Content-Security-Policy was absent from the response." \
--remediation "Deploy a restrictive Content Security Policy."Additional v0.3 optional flags are also available:
pwnreport finding add demo-report/report.json \
--reproduction-steps "Step A,Step B,Step C" \
--references "CWE-693,OWASP A05:2021" \
--cvss-vector "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" \
--cvss-score "9.8" \
--remediation-status "open"PwnReport assigns IDs automatically in FIND-001 format. It derives the next
ID from the highest existing numeric finding ID rather than reusing deleted
numbers.
Inspect and validate findings before building the report:
pwnreport finding list demo-report/report.json
pwnreport finding show demo-report/report.json FIND-001
pwnreport validate demo-report/report.jsonFinding changes are validated before saving. PwnReport writes a temporary file
beside report.json, flushes it to disk, and atomically replaces the original.
Unknown JSON fields are preserved, so adding a finding does not discard custom
metadata maintained by another tool.
PwnReport v0.4 normalizes five common export formats:
| Importer | Supported input | Normalization behavior |
|---|---|---|
| Nuclei | JSONL or JSON array | Template metadata, severity, matched asset, evidence, CVSS, CWE/CVE |
| Burp Suite | XML issue export | Issue detail, request/response evidence, confidence, remediation |
| Nmap | XML | One informational finding for each open port and service |
| Nessus | .nessus XML |
Plugin result, host/port, risk, output, CVSS, CWE/CVE |
| Custom | JSON object, array, or findings[] |
Common aliases such as name, host, proof, and recommendation |
Examples:
pwnreport import nuclei demo-report/report.json nuclei-results.jsonl
pwnreport import burp demo-report/report.json burp-issues.xml
pwnreport import nmap demo-report/report.json nmap-results.xml
pwnreport import nessus demo-report/report.json assessment.nessus
pwnreport import custom demo-report/report.json custom-findings.jsonEvery imported finding receives a new FIND-NNN ID and provenance metadata:
"source": {
"tool": "nuclei",
"source_id": "missing-csp",
"file": "imports/nuclei/nuclei-results.jsonl"
}The original export is copied into imports/<tool>/ without overwriting a
previous import. Parsing and combined-report validation complete before the
source is published or report.json is changed. If the report save fails, the
new source copy is removed. XML containing DOCTYPE or ENTITY declarations
is rejected, and import files are limited to 25 MiB.
The initial template is intentionally small:
{
"project": {
"name": "Web Application Penetration Test",
"client": "ACME Corporation",
"assessment_type": "Web Application",
"classification": "CONFIDENTIAL",
"author": "Rizko Febri Rachmayadi"
},
"scope": [
"https://app.example.com"
],
"executive_summary": "The assessment identified one high-risk vulnerability.",
"findings": [
{
"id": "FIND-001",
"title": "SQL Injection in Login Endpoint",
"severity": "high",
"affected_asset": "https://app.example.com/login",
"description": "The login endpoint does not safely handle user input.",
"impact": "An attacker may access or modify sensitive application data.",
"evidence": "A crafted input changed the authentication response.",
"remediation": "Use parameterized queries for all database operations."
}
]
}Allowed severity values, in report order:
critical, high, medium, low, info
All project fields and the eight core finding fields are required. The v0.3
detail fields and v0.4 source provenance object are optional. Finding IDs
must be unique, and invalid input stops the operation with a readable error.
The roadmap is intentionally incremental. Each stage should preserve the simple JSON-first workflow and remain useful on its own.
Delivered foundation:
- Minimal report schema
-
initandbuildCLI commands - Required-field and severity validation
- Duplicate finding ID detection
- Severity-based finding ordering
- Self-contained dark-theme HTML output
- Browser print stylesheet for optional PDF export
- Standard-library test suite
Delivered:
Make authoring reports easier without introducing a database:
-
pwnreport finding add -
pwnreport finding list -
pwnreport finding show <id> -
pwnreport validate <report.json> - Automatic finding ID generation
- Safer editing while preserving the JSON schema
Delivered:
Extend the schema for findings that need more technical context:
- Reproduction steps
- Evidence file references (references field)
- CWE, CVE, and OWASP mappings (references field)
- CVSS vector and score fields
- Methodology and limitations sections
- Remediation status
Current release:
Normalize common tool output into the PwnReport schema:
- Nuclei JSONL importer
- Burp Suite issue export importer
- Nmap result importer
- Nessus result importer
- Generic custom JSON importer
The original source files should remain available in the project workspace so the final report can be traced back to the tool output.
Delivered:
- Native PDF export
- Markdown export
- Table of contents
- Client logo and branding fields
- Report metadata and report date
- Multiple report templates
- Light and dark themes
Delivered:
- Multiple projects and report history
- Reusable finding library
- Finding deduplication across assessments
- Scope and asset management
- Review and approval workflow
- Optional local web interface
- Optional team collaboration
The roadmap does not make PwnReport responsible for reconnaissance or exploitation. Scanner and assessment tools remain separate inputs, while PwnReport focuses on normalization, validation, and report delivery.
Run the standard-library test suite:
python3 -m unittest discover -s tests -vMIT