| name | pentest-report |
| description | Use when the user asks to "write up a pentest report", "assemble a security assessment deliverable", or convert audit outputs into a client-ready document. Produces a structured report with executive summary, methodology, scope, findings (CVSS + CWE + remediation), risk matrix, and raw-evidence appendix from scanner JSON plus manual notes. |
| safety | writes-local |
When to use
Trigger on any of:
- "Write the pentest report from these findings."
- "Turn
security-audit's output into a deliverable for the customer."
- "Prepare the Q3 security assessment document."
- End of an internal red-team engagement that already has a findings list.
Do not use to perform the assessment. This skill only assembles the report
from evidence already collected.
Inputs
AUDIT_DIR — directory containing scanner outputs (the OUT_DIR from
security-audit typically). Required.
MANUAL_NOTES — optional path to a markdown file with findings the
tester documented by hand.
ENGAGEMENT_META — YAML with engagement name, client, tester(s), dates,
scope list, methodology notes.
OUT_FILE (default: ./pentest-report.md).
Example ENGAGEMENT_META:
engagement: "Q3 2026 External Web App Assessment"
client: "Acme Corp"
testers:
- "Taylor Reyes <taylor@secfirm.example>"
window:
start: "2026-04-05"
end: "2026-04-12"
scope:
in:
- https://app.acme.example
- https://api.acme.example
out:
- https://blog.acme.example
methodology:
- "OWASP WSTG v4.2"
- "PTES Technical Guidelines"
Outputs
$OUT_FILE — markdown report matching references/report-template.md.
pentest-report.findings.json — machine-readable finding list used during
assembly (kept for regeneration / re-export to DOCX/PDF).
pentest-report.risk-matrix.csv — risk matrix data.
Tool dependencies
jq to read scanner outputs.
pandoc (optional) to convert $OUT_FILE to DOCX/PDF for client delivery.
cvss-cli (optional) to recompute vectors when raw vectors are present.
Procedure
- Load
ENGAGEMENT_META and validate required fields (client, window,
scope, testers).
- Collect findings:
- From
$AUDIT_DIR/findings.normalized.json (security-audit output).
- From
$AUDIT_DIR/secrets.deduped.json (secret-scanner output).
- From
$AUDIT_DIR/dep-audit.normalized.json (dependency-audit output).
- From
$MANUAL_NOTES (parsed: each H3 becomes a finding).
- Normalize each finding into the report schema:
{ title, severity, cvss_score, cvss_vector, cwe, description,
evidence (markdown block with code fences + image refs),
impact, remediation, references[], status }
- Deduplicate across sources by
(cwe, affected_asset) — if two scanners
found the same issue, merge evidence blocks and keep the higher CVSS.
- Assign each finding a stable ID:
FIND-<YEAR>-<0-padded-index>.
- Assemble the document per
references/report-template.md:
- Title page + engagement metadata.
- Executive Summary (non-technical; counts per severity; business impact
paragraph; 3 headline recommendations).
- Scope (in/out, test windows, test accounts used).
- Methodology (tools, frameworks cited from meta).
- Findings (ordered by severity desc, then CVSS desc).
- Risk Matrix (Impact x Likelihood 5x5, each cell lists finding IDs).
- Recommendations (strategic, beyond per-finding fixes).
- Appendix A: Raw evidence pointers (relative paths into
$AUDIT_DIR).
- Appendix B: Tool versions.
- Emit
pentest-report.risk-matrix.csv:
finding_id,likelihood(1-5),impact(1-5),risk(likelihood*impact).
- Optionally convert:
pandoc $OUT_FILE -o pentest-report.docx --reference-doc=corp-template.docx.
Examples
Example 1 — Assemble from a security-audit run
AUDIT_DIR=/tmp/audit-checkout \
ENGAGEMENT_META=./engagement.yaml \
OUT_FILE=./checkout-pentest.md \
./assemble.sh
Expected head of checkout-pentest.md:
# Q3 2026 External Web App Assessment
**Client:** Acme Corp
**Testers:** Taylor Reyes <taylor@secfirm.example>
**Window:** 2026-04-05 – 2026-04-12
**Document status:** FINAL v1.0
## Executive Summary
During the seven-day assessment, one Critical and four High-severity issues
were identified. The Critical issue (FIND-2026-001) allows unauthenticated
order manipulation via an IDOR in /api/orders and should be remediated
within 24 hours per Acme's SLA. ...
Example 2 — Merge manual + scanner findings
AUDIT_DIR=./scans \
MANUAL_NOTES=./manual-findings.md \
ENGAGEMENT_META=./engagement.yaml \
./assemble.sh
Expected log:
[pentest-report] scanner findings: 27 (dedup: 19)
[pentest-report] manual findings: 4
[pentest-report] merged total: 22 (1 critical, 4 high, 9 medium, 8 low)
[pentest-report] wrote ./pentest-report.md (48 KB)
[pentest-report] wrote ./pentest-report.findings.json
[pentest-report] wrote ./pentest-report.risk-matrix.csv
Constraints
- Never fabricate CVEs, CWE IDs, or CVSS vectors. If unknown, leave blank
and flag
needs_review: true.
- Never include real secret material in the report, even in evidence — use
the redacted form from
secret-scanner.
- Client-identifying data stays in the engagement metadata; do not copy
customer names into tool output filenames.
- Evidence screenshots must reference local paths in
$AUDIT_DIR/evidence/ — the report consumer places them later.
- Every High or Critical finding must include a remediation with a
code-level change description or a config-level change, not just
"apply patches".
Quality checks