What a penetration test report should actually tell you
Most reports are a scanner export with a logo on it. Here is what to demand instead — and how to tell in ten minutes whether you were sold real testing.
A red pen over a printed page
Close crop of one hand holding a red pen above a printed page, mid-annotation. Bare pale surface, nothing else in frame. The pen is the only colour.
2400×1350 · WebP · <350KB
You can usually tell within ten minutes. Open the report, go to a finding, and ask one question: could my engineer fix this on Monday using only what is written here? If the answer is no, you did not buy a penetration test. You bought a scanner licence with a consultant's letterhead on it.
The tell: severity without a story
A scanner produces a list. Forty findings, each with a CVSS score, each independently true, and none of them connected. A tester produces a narrative: this forgotten subdomain exposed a staging login, staging shared a password with production, and production had no MFA on administrative accounts. Individually those three are medium, medium, and low. Chained, they are how someone owns your environment before lunch.
If your report has no chain in it — no sentence beginning "combining findings 12, 19 and 27" — nobody actually tested you. They pointed a tool at you.
Forty findings ranked by score tells you what a scanner noticed. Nine findings ranked by what an attacker would do with them tells you what to fix.
What every finding needs
- Reproduction steps your engineer can follow without calling the tester. Exact request, exact parameter, exact precondition.
- Evidence. A screenshot or a captured response proving the issue is real, not theoretical.
- Impact in your terms. Not "information disclosure" — "an unauthenticated user can enumerate every customer email address".
- A fix that names the thing. The file, the config key, the header. Not "implement input validation".
- An honest severity, adjusted for your environment. An RCE on an isolated box with no data is not a critical, whatever the scanner said.
The parts most reports skip
A good report also tells you what was not tested and why. Scope boundaries, systems that were out of bounds, credentials that never arrived, the environment that was down for two days of the window. Those gaps are risk you still carry, and hiding them makes the report look better while leaving you less safe.
It should tell you what held up, too. If your WAF blocked the injection attempts and your EDR killed the payload, that belongs in writing. You paid for it; you should be able to prove it works.
Retesting is part of the job
A finding is not closed because a ticket was closed. It is closed because someone tried the exploit again and it failed. Any firm charging separately to verify their own findings has an incentive you do not want in the relationship. Retesting should be included, and the reissued report should show the finding struck through with the date it was verified.
A short checklist
- Is there at least one chained attack path, written as a narrative?
- Can an engineer reproduce the top finding without asking a question?
- Does every fix name a file, a setting or a header?
- Is there a section on what was out of scope or untested?
- Is a retest included, and by when?
- Were critical findings reported during the test, not saved for the debrief?
That last one matters more than the rest combined. If a tester finds a live compromise or an internet-facing critical on day two, you should hear about it in the hour. Learning it from a PDF three weeks later is not a reporting style. It is negligence.