How to read a penetration test report
A good penetration test report is written to be acted on, not filed. But most people who receive one have never been taught to read it, and the sections that look most authoritative — the severity table, the CVSS scores — are the ones most likely to have you fixing things in the wrong order. Here is how to work through a report properly: what each part is for, how to tell a real finding from a scanner echo, and how to sequence the work that follows.
The anatomy of a report
Reports vary in house style, but a complete one has the same five parts, each answering a different question.
- Executive summary. Overall risk and recurring themes, for leadership — short and free of jargon. Its job is to let a non-technical reader decide something.
- Scope and methodology. What was tested, how, from where, with what access — and, critically, what was not tested.
- Findings. One entry per issue: severity, affected component, evidence, reproduction steps, business impact, recommended fix.
- Remediation plan. The findings re-ordered by real risk rather than raw score, ideally grouped by root cause.
- Retest results. Written confirmation of what has been fixed.
Read them in an unintuitive order: scope and methodology, then the executive summary, then the remediation plan, and only then individual findings. Findings are meaningless without knowing what was in scope and what access the tester had. A report with no critical findings means one thing if the tester held credentials for every role, and something quite different if they had an unauthenticated view of a login page.
So extract three facts from the scope section first: what was in scope, what access the tester held, and what the report says was not reached. That last is the most valuable sentence in most reports and the most frequently skipped. "The reporting module was not reached within the engagement period" describes a gap in your assurance, not a failure — and absence of findings in an area nobody opened is not a result.
Reading the executive summary as a non-technical reader
If you are reading the summary to make a decision rather than to fix anything, you want four things, none of them a number.
The themes. Good summaries name patterns rather than listing issues: authorisation enforced inconsistently across services, input validation applied at the interface but not at the API, secrets managed by convention rather than tooling. Themes are what you act on organisationally, because themes recur and individual bugs do not.
The worst realistic outcome. Not the highest severity label, but the sentence describing what an attacker could actually achieve — read customer records, authorise a payment, take over an administrative account. If no such sentence exists, either nothing significant was achievable, which the report should say plainly, or the writer has retreated into categories.
Whether anything requires action this week, separated from what can wait for the normal cycle. If the summary does not say, the remediation plan should.
What changed since last time. For a repeat engagement the comparison matters more than the absolute picture. Are the same root causes reappearing in new code? That is a process finding, and it will not be in the findings table.
One caution on counts: a low total may simply reflect a narrow scope, and forty entries of which thirty are informational describe a healthier system than five of which two are authentication bypasses. Count the top of the table, not its length.
What severity ratings mean, and why CVSS is informative rather than decisive
Severity labels are a starting point, not an answer. They exist so you can sort a long list quickly, and they are usually derived from CVSS — a framework rating a vulnerability's intrinsic characteristics: how it is reached, how hard it is to exploit, what privileges it needs, and its effect on confidentiality, integrity and availability.
That framework is genuinely useful, and it is genuinely not a risk score, because it is deliberately context-free. CVSS does not know that the affected component holds cardholder data, or that it is an internal tool used by four people, or that one route is reachable from the internet while an identical defect sits behind a VPN. It asks "what is this flaw?" rather than "what does this flaw mean here?" — the question you need answered.
The practical consequence is one every experienced reader learns quickly: a medium on your payment flow routinely matters more than a high on an internal reporting tool. Three factors convert a label into a decision.
- The value of what it exposes — whose data, which system of record, what financial or regulatory consequence follows.
- Reachability — internet-facing and unauthenticated, or requiring a privileged internal account and a specific sequence? This is where context changes the picture most.
- Chainability — independent severity can be low while the contribution to a chain is decisive. A disclosure that leaks valid usernames is unimportant alone and essential to a credential-stuffing path.
Chains deserve particular attention, because they are where real compromise comes from and where severity tables mislead most. Three mediums composing into account takeover are a critical problem described in three places. A good report says so, sets out the sequence, and names the cheapest link to break — breaking one neutralises the chain while you address the rest.
So treat the severity column as a sort order, the remediation plan as the recommendation, and your knowledge of the business as the deciding input.
What this means for you
- Read scope and methodology first. Findings cannot be interpreted without knowing the scope and the tester's access.
- Write down what was not tested. It is the part of your assurance picture the report cannot cover.
- Re-rank by business context: severity, times the value of what is exposed, times how reachable it is.
- Find the chains before you schedule anything, and ask which link breaks each one most cheaply.
- Judge the report by its top entries, not by how many there are.
Telling a real finding from a scanner echo
The difference between a penetration test and a scan with a cover page is visible in the findings themselves. Work through the entries and ask what the author actually demonstrated; a real finding has four properties.
- Specific to your system. It names the endpoint, the parameter, the role, the object identifier. A scanner echo is generic — written about the vulnerability class rather than your instance of it, and applying unchanged to any application anywhere.
- It shows the outcome, not the trigger. "Reflected input was returned unencoded" is a trigger; "submitting this payload as an authenticated user transmits the session token to an external host" is an outcome. Scanner-derived reports stop at the trigger, because the tool stops there.
- Impact in your language. Not "may lead to information disclosure" but "an authenticated customer can retrieve another customer's invoices, including name, address and payment history". The second can be taken to a product owner; the first cannot.
- An implementable recommendation — what to change and where: this validation belongs server-side in this handler, this check must move to the data layer. An echo says "implement proper input validation".
Three further signals. Version-only findings — "component X is at version Y, affected by CVE-Z" — are candidates, not conclusions: version strings are frequently wrong, back-ported patches are common, and the vulnerable path may not be reachable in your configuration. Legitimate as a patching observation; not evidence of exploitability unless the tester confirmed it, and a good report distinguishes the two. Severity inflation on best-practice items: a missing header or unflagged cookie is worth reporting, but reported as high it is padding. And recorded disproofs, a strong positive signal — "we attempted to bypass the tenant filter by these three routes; all were correctly enforced" is assurance, and shows the tester knew what to try.
What good evidence and reproduction steps look like
Evidence exists so that a finding survives disagreement. The test: could one of your engineers, with the report and nothing else, reproduce the issue and then confirm the fix? If not, the finding will be disputed, and disputed findings do not get fixed.
Adequate evidence is complete — the full request and response, including the headers and token placement that make the request work, not a cropped browser screenshot. It is attributable: clear which account, role and tenant acted, which is the whole point in an access-control finding, where the actor's identity is the vulnerability. It is bounded, demonstrated without exfiltrating more data than needed. And it is repeatable: numbered steps from a stated starting state — log in as role A in tenant 1, create an object, note its identifier, then make this request as role B in tenant 2.
Watch for the weak patterns: steps beginning mid-sequence; screenshots as the only evidence for an API finding, where the raw exchange is what matters; identifiers that no longer exist, leaving the issue unverifiable. And missing negative evidence — an access-control finding should show both that role B succeeded and that the system was supposed to prevent it, or you cannot tell a vulnerability from a permission you forgot you granted. If a finding fails these tests, ask for the evidence rather than quietly dropping it; a tester who found something real can supply it. For a standard to compare against, read a full report end to end.
How to triage and sequence remediation
Work in this order.
First, fix anything that leads directly to account or data compromise — authentication bypass, broken access control exposing other customers' records, remote code execution, exposed credentials. If the full fix will take weeks, deploy a mitigation this week — disable the route, restrict access at the network layer, revoke the key — and record it as a mitigation, not a resolution.
Second, group by root cause. The highest-leverage move available, and the one most often skipped. Twelve findings across different endpoints frequently reduce to three causes: authorisation checked in the controller instead of the data layer, a validation helper applied inconsistently, a shared library out of date. Fixing the cause closes every instance and prevents the next one; fixing twelve instances individually guarantees a thirteenth.
Third, deal with the chains. Identify each multi-step path, break the cheapest link immediately, then fix the remaining links on a normal schedule.
Fourth, batch the rest by owner and deployment: everything touching one service in one change, everything in configuration in another. Six low findings in the same template are one ticket.
Fifth, decide explicitly about what you will not fix. Some findings will be accepted rather than remediated: the component is being decommissioned, or the fix costs more than the exposure. Legitimate, but it must be a written decision with an owner and a review date, not a ticket that ages out. "We never got to it" and "we assessed it and accepted it" are very different answers to an auditor.
Throughout, track findings in the system you already use for engineering work, with the report's finding reference on each ticket; a separate security spreadsheet goes stale within a month and competes with the backlog instead of entering it. Record the cause, not just the instance.
READING A PENETRATION TEST REPORT
BEFORE THE FINDINGS
[ ] What was in scope, asset by asset
[ ] What access the tester held (roles, credentials, source, docs)
[ ] What the report says was NOT tested or not reached
[ ] Environment: production or staging, and the differences
[ ] Themes named in the executive summary
[ ] The worst realistic outcome, stated in one sentence
[ ] For a repeat test: which root causes have reappeared
PER FINDING, CHECK
[ ] Specific to our system: endpoint, parameter, role, object
[ ] Demonstrates an outcome, not just a trigger
[ ] Impact written in our language, not "may lead to disclosure"
[ ] Fix is implementable: what to change, and where
[ ] Evidence complete: full request and response, not a crop
[ ] Attributable: which account, role and tenant acted
[ ] Reproducible: numbered steps from a stated starting state
[ ] Access-control findings show the control SHOULD have blocked it
[ ] Version-only? Treated as a candidate, not a conclusion
[ ] Severity justified by privilege and action, not by class
RE-RANK BY CONTEXT
[ ] Value of what each finding exposes
[ ] Reachability: internet-facing / authenticated / privileged
[ ] Chainability: which lows are links in a serious path
[ ] Chains identified, with the cheapest link to break
SEQUENCE THE WORK
[ ] Account or data compromise paths first
[ ] Same-week mitigation where the full fix is slow (recorded as such)
[ ] Group by root cause before scheduling anything
[ ] Break the cheapest link in each chain
[ ] Batch remaining findings by owner and deployment
[ ] Accepted risks written down, with owner and review date
[ ] Tickets in the normal engineering system, with finding references
RETEST MUST CONFIRM
[ ] Original reproduction steps no longer work
[ ] Root cause fixed, not just the reported instance
[ ] Fix cannot be trivially circumvented
[ ] Status per finding: resolved / partial / mitigated / open
[ ] Anything the fix itself introduced
[ ] Confirmation issued as a document you can hand onwards
KEEP TOGETHER FOR AUDIT AND CUSTOMERS
[ ] The report
[ ] The retest confirmation
[ ] Risk-acceptance decisions with dates and owners
[ ] The note on what was not tested
What a retest should confirm
The retest converts a report into a change in your security position. Until it happens, you have a list of things you believe you fixed.
A proper retest confirms three things per finding, and the third distinguishes it from a re-scan. That the original reproduction steps no longer work. That the root cause is addressed, not the instance: a fix applied to one endpoint while the pattern remains elsewhere does not close the finding. And that the fix cannot be trivially circumvented, which is where incomplete remediation shows up — validation added client-side while the API still accepts the request; an identifier obfuscated rather than authorised, so the check is harder to reach but still absent; an endpoint removed from the interface while remaining live.
Expect a clear status per finding — resolved, partially resolved, mitigated or open — with evidence for each, and a note on anything the fix introduced, since remediation sometimes creates new behaviour. Those four words are not interchangeable, and an assessor reads them literally. Ask for the confirmation as a document you can hand onwards, and keep it with the report.
What this means for you
- Fix compromise paths first, with a same-week mitigation where the full fix is slow — recorded as a mitigation.
- Group by root cause before you schedule. One fix usually closes several findings and prevents the next.
- Track findings in your normal engineering system, with the report reference on each ticket.
- Make risk acceptance a written decision with an owner and a review date.
- Book the retest before remediating, and insist it checks root cause and circumvention, not just the original steps.
Questions for your debrief
The debrief is where you get what does not fit in a document.
- What is the single most important thing to fix this week?
- Which findings are chained, and does fixing one break the chain?
- What would stop these issues recurring, rather than fixing this one?
- What did you not have time to test that we should scope next?
- What surprised you about this system — good or bad?
- Which finding are we most likely to fix incorrectly?
- What did you try that did not work, and why?
The last three are rarely asked, and "what are we most likely to fix incorrectly" in particular saves a failed retest.
Using the report with an auditor or a customer
Keep the report: your auditor and your customers' security reviewers will ask for it, and both read it differently from your engineers.
An auditor is checking that a control operated: that testing was performed by a competent independent party, covered the relevant environment, and that findings were assessed, tracked and either remediated or consciously accepted. What they need is the scope section matching the system under assessment, dated evidence of the tracking and decisions, and the retest confirmation. The findings matter less than the demonstrable process around them — which is why an unretested report with a stale spreadsheet behind it creates audit problems that a report with several high findings and clean closure evidence does not.
A prospective customer asks a different question: are you a safe supplier? Most do not need the full report, and sharing it unredacted hands over a map of your internals, so ask what they require. Usually a summary letter confirming the test, its scope, period and the independent party; confirmation that findings above a threshold were remediated and retested; and your testing cadence. Where the full report is genuinely required, share it under NDA, consider removing reproduction detail, and send the retest confirmation alongside — without it the report reads as a list of open vulnerabilities.
Keep the set together: report, retest confirmation, risk-acceptance decisions, and the note on what was not tested. That bundle answers nearly every question either audience asks, and it is the right starting point for the next engagement.
For the condensed version to take into a debrief, the one-page guide to reading a report puts the sections, prioritisation rules and debrief questions on a single sheet. For how we report engagements, see our penetration testing service.
See a full report end to end
Our 26-page sample report shows every section this article describes, with the evidence and the fixes.
Read our sample report