Security · · 2 min read
What a pentest report should contain
A report is only worth paying for if your developers can act on it. Here is what to expect on every finding, and what to send back if it is missing.
A penetration test ends with a document. If that document is a list of scanner output with a logo on top, the test was wasted, however good the testing was. This is what we put in every report, and what you should expect from anyone you hire.
1. A summary a non-engineer can read
One page. What was tested, when, and the answer to the question the business cares about: could an attacker get to customer data, money or admin access? If yes, how hard was it?
No tool names and no jargon on this page. The person who signs the budget reads it.
2. Scope and limits
The report should list exactly what was in scope: domains, IP ranges, app versions, user roles and the testing dates. It should also say what was left out and why.
This matters later. A clean report on app.example.com says nothing about admin.example.com if the admin site was never tested.
3. For every finding: severity, proof and the fix
Each finding needs all of these:
- A plain title. "Any customer can read another customer's invoices" beats "IDOR in invoice module".
- Severity, with the reasoning. High, medium or low, and why: what an attacker needs and what they get.
- Proof. The request and response, or a screenshot, that shows the problem is real. Your developers should be able to reproduce it in 5 minutes.
- Impact in business terms. What data or action is exposed.
- The fix. A concrete change. "Check on the server that the invoice belongs to the signed-in user" is a fix. "Improve access controls" is not.
Here is the proof section from a typical access control finding:
GET /api/invoices/10482
Cookie: session=<customer A>
200 OK
{ "customer": "B", "total": "4,310.00" }
Customer A asked for an invoice that belongs to customer B and got it. Nobody needs a paragraph to understand that.
4. Findings that were checked and ruled out
Scanners produce false positives. A good report says which alerts were checked by hand and dismissed, so your team does not spend a week chasing them.
5. A retest
A fix is not done until someone tries the attack again and it fails. Ask for a retest to be part of the engagement, and for the report to be updated with the result of each one.
What to send back
Push back on a report if:
- Findings have no proof
- Severity is copied from a scanner with no explanation
- Fixes are generic advice that could apply to any app
- You cannot tell what was and was not tested
You paid for someone to think like an attacker. The report is where you see whether they did.
More notes
Want this checked on your own product? Send us the brief.