   
                             
                   
                                                                            
                                                                                                                                                                                                                 
                  
                     
           
                                           
                                                                      
   
A pentest report is the only artifact most stakeholders will ever see, and it is read by two audiences who do not want the same thing. The board wants to know whether you are a bigger or smaller problem than the last firm; the engineers want to know exactly which line of code to change and why. A report that addresses only one of them is not finished.

## Two audiences, two documents in one

I structure every engagement deliverable as a pair of documents bound together: an executive summary of three to five pages that opens the report, and a technical appendix of however many pages the findings require, that ends it.

They are written for different readers and they look different on the page. The only thing they share is the table of findings, reproduced in both and sorted differently.

> [!NOTE: Rule of thumb] If a finding's executive paragraph and its technical paragraph could be swapped without losing meaning, you have written one of them badly.

## The executive summary

Three pages. Sometimes four. Never more. The executive summary answers four questions, in this order, and stops:

1. What did we test, and what did we not test? Scope, scope boundaries, what was excluded and why.
2. What was the worst we could do? One paragraph per critical/high finding, in plain language. No CVE numbers; no protocol jargon. The verb is could, not did.
3. How does this compare to a reasonable baseline? Calibrated against the size of the organization and the threat model in scope.
4. What changes in the next quarter, if you act on this report? The remediation plan, expressed as outcomes, not tickets.

> I do not need to know what XSS is. I need to know how exposed I am, and what I get for the next million euros of security spend.
>
> — every executive who has read a pentest report

## The technical appendix

Each finding gets a numbered chapter that follows a fixed structure. Engineers are pattern-matchers; once they know the structure, they can scan the report at three times the speed of an unstructured one.

```text
# F-NN  <Title — single sentence, action verb removed>

Severity: <Critical | High | Medium | Low | Info>
CVSS:     <vector + score>
Status:   <Confirmed | Suspected | Theoretical>

## Where
<Path, parameter, host, line of code. Specific. Reproducible.>

## What
<Two paragraphs. What the bug is, mechanically. No remediation.>

## Why it matters
<One paragraph. The blast radius if exploited. Plain language.>

## How to reproduce
<Numbered steps. Copy-paste-able. Everything needed to verify a fix.>

## Evidence
<Screenshots, request/response pairs, logs. Captioned and dated.>

## Remediation
<What to change. Multiple options if there are real trade-offs.>
```

## On severity

I use CVSS for the score and sleep on it for the rating. CVSS gives a number; the number does not always agree with how a competent attacker would rank the same finding. A 4.3 in CVSS that I can chain into a 9.0 outcome is a 9.0 finding in my report, and the chain is in the body. The score is a measurement, not a verdict.

## Diagrams earn their place

A diagram in the report is doing one of three jobs: showing the network as it was observed, showing the data flow for an exploit chain, or showing the recommended fix's place in the architecture. If your diagram is doing a fourth thing, decoration, delete it. Reports are not slides.

<figure class="figure">
<div class="frame">
<div class="figure-plain" style="min-height:180px;">
<svg viewBox="0 0 600 160" width="100%" height="160" role="img" aria-labelledby="report-diagram-title report-diagram-desc" style="display:block;">
<title id="report-diagram-title">A report diagram showing a violated trust boundary</title>
<desc id="report-diagram-desc">An untrusted system sends an X-Forwarded-User header across a trust boundary into a trusted system. The violating data flow is shown in red.</desc>
<defs>
<marker id="report-flow-arrow" markerWidth="8" markerHeight="8" refX="1" refY="4" orient="auto">
<path d="M8 0 L0 4 L8 8 z" fill="rgb(228, 12, 50)"></path>
</marker>
</defs>
<rect x="40" y="50" width="160" height="60" rx="2" fill="rgba(73, 82, 234, 0.08)" stroke="rgb(73, 82, 234)" stroke-width="1.4"></rect>
<text x="120" y="84" text-anchor="middle" style="font-family:var(--font-utility);font-size:12px;font-weight:600;fill:var(--fg-page);">Trusted</text>
<rect x="400" y="50" width="160" height="60" rx="2" fill="transparent" stroke="rgb(82, 82, 91)" stroke-width="1.4" stroke-dasharray="4 3"></rect>
<text x="480" y="84" text-anchor="middle" style="font-family:var(--font-utility);font-size:12px;font-weight:600;fill:var(--fg-page);">Untrusted</text>
<path d="M400 80 L200 80" stroke="rgb(228, 12, 50)" stroke-width="2" fill="none" marker-end="url(#report-flow-arrow)" stroke-dasharray="5 4"></path>
<text x="300" y="68" text-anchor="middle" style="font-family:var(--font-mono);font-size:11px;fill:rgb(228, 12, 50);font-weight:600;">X-Forwarded-User</text>
<text x="300" y="106" text-anchor="middle" style="font-family:var(--font-mono);font-size:10px;fill:var(--fg-faint);">boundary breach</text>
</svg>
</div>
</div>
<figcaption><span class="fnum">Fig. 1</span><span>A diagram I'd ship: shows the trust boundary that was violated, with the violating data flow in red. Two colors, no decoration.</span></figcaption>
</figure>

## What goes after the report

A draft, a revision pass with the engineering team to catch anything I got wrong, and a presentation to the people who pay for the engagement. The presentation is not the report; it has its own structure and its own rhythm. That is a different essay.
