Skip to main content

How to write a penetration test report

The report is the deliverable. Your client never watches you work, so everything they pay for arrives in the document you hand over at the end. A good penetration test report is judged on three things: whether it is accurate, whether a reader can understand the risk, and whether an engineer can act on it the next morning. Reporting also takes a large share of engagement time, much of it spent rebuilding the same structure and rewriting the same findings from job to job.

This guide walks through each section of a standard penetration test report, what belongs in it, and how to keep your writing consistent across engagements. The worked example uses the structure NullReport ships with, but the advice applies whatever tool you write in.

Know who is reading

Two very different people read the same report. An executive or asset owner skims the first page to learn whether they have a problem, how bad it is, and what it will cost to fix. An engineer reads the findings in detail to reproduce each issue and close it. Write for both by separating the layers: a short, plain-language summary at the front, and precise technical detail in the findings. When you blur the two, the executive drowns in payloads and the engineer cannot find the steps to reproduce.

The standard structure

Most penetration test reports follow the same skeleton, and clients expect it:

  1. Executive summary
  2. Scope
  3. Methodology
  4. Findings summary
  5. Detailed findings
  6. Recommendations
  7. Appendices

NullReport creates a new report with Executive Summary, Scope, Methodology, Findings Summary, and Recommendations as default sections, and holds your findings separately so they can be reused and reordered. You can rename or reorder any of this in Settings.

Executive summary

Write this section last, even though it comes first. It is the only part many stakeholders read, so it has to stand on its own. State what was tested, the overall risk in business terms, and the two or three things that matter most. Name the count of findings by severity, and say plainly whether the environment is in good shape or needs urgent work.

Keep payload details and tool names out of it. "An attacker who reached the login page could read any customer's records without a password" tells an executive more than a CVSS vector ever will. If you cannot explain a finding's impact in one sentence a non-technical reader understands, you do not yet understand the impact well enough to write the finding.

Scope

Scope is the section that protects you. Record exactly what was in and out of the engagement: the hosts, applications, domains, or accounts you were authorized to test, the testing window, the type of assessment, and any rules of engagement. Note anything you were asked to avoid, any system that was unavailable, and any constraint that limited coverage, such as a rate limit or a staging environment that did not match production.

Be explicit about caveats. A penetration test is a point-in-time sample, not a proof that no vulnerability exists. Saying so in the scope section sets honest expectations and keeps a future incident from being blamed on your report.

Methodology

Methodology tells the reader how you reached your conclusions, which is what makes them credible and repeatable. Describe your approach and reference the standards you followed, such as the OWASP Testing Guide, the Penetration Testing Execution Standard, or NIST SP 800-115. List the main phases you worked through, for example reconnaissance, enumeration, exploitation, and post-exploitation, and the categories of test you performed.

You can reuse most of this section verbatim between engagements of the same type. That is a feature, not a shortcut. A consistent methodology section signals a consistent process.

Findings: the core of the report

Everything else supports the findings. Each finding documents one issue, and writing one issue per finding keeps severities honest and remediation specific. A complete finding has:

  • Title. Name the vulnerability and where it is, for example "SQL injection in the login form".
  • Severity. A single rating a reader can scan. See the next section.
  • Affected assets. The specific hosts, endpoints, or parameters involved.
  • Description. What the vulnerability is, in a few sentences.
  • Evidence. The steps to reproduce, the request and response, and screenshots. This is what lets an engineer confirm the issue without calling you.
  • Impact. What an attacker gains, stated in terms of the client's data and systems.
  • Remediation. How to fix it. See Remediation below.

NullReport gives each finding Description, Details, Impact, and Remediation fields by default, and you can add or rename fields in Settings. Every field is the same rich-text editor, so command output, tables, and screenshots all go inline and carry through to the export.

Severity and CVSS

Severity is the shared language between you and the reader, so rate consistently. The Common Vulnerability Scoring System, version 3.1, gives you a defensible number and a vector string that shows your reasoning, for example CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. NullReport has a CVSS v3.1 calculator built in, so you set the metrics and the score and severity fill in.

Let context adjust the label. A high CVSS score on a system with no sensitive data may be a lower real risk to the client than a medium score on the crown-jewel database. When you override the raw score, say why in the finding. The default severity levels are Critical, High, Medium, Low, and Info, and you can recolor or relabel them to match your house style.

Remediation

A finding that only describes a problem leaves the client stuck. Tell them how to fix it, as specifically as the issue allows. "Use parameterized queries for the username parameter in the login handler" is actionable. "Improve input validation" is not. Where a full fix takes time, offer an interim mitigation as well, and order your recommendations so the client knows what to do first.

The Recommendations section at the end of the report is the place to step back and give the strategic view: the themes you saw across findings, the root causes worth addressing once rather than patching symptom by symptom, and the priorities for the next quarter.

Findings summary

Before the detailed findings, give the reader a one-page overview they can scan: the total count, a breakdown by severity, and a table listing each finding with its severity and affected asset. This is where summary counts earn their place. In a NullReport template you can drop in {{total_findings}}, {{critical_count}}, {{high_count}}, and the rest, then loop over your findings to build the table automatically:

| ID | Finding | Severity |
|----|---------|----------|
{{#findings}}
| {{_num | changeID:'FINDING'}} | {{title}} | {{severity}} |
{{/findings}}

See Template Syntax for the full loop, conditional, and filter reference.

Appendices

Put the bulk material at the back: full tool output, complete lists of tested endpoints, raw vector strings, and any methodology detail that would interrupt the findings. Keeping it out of the body lets the report read cleanly while still giving a thorough reader everything they need.

Make it repeatable

The single biggest improvement you can make to your reporting is to stop starting from a blank page. The same vulnerabilities recur across engagements, and rewriting them from memory each time is where consistency and hours both leak away.

This is the workflow NullReport is built around. Write a finding once and save it to your finding library, then drop it into any future report and adjust the specifics. Keep your sections and severities as defaults so every new report starts in your house style. Write the whole report against your own branded .docx template, so the export comes out formatted, with colored severity badges, ready to deliver. See Exporting for how the final document is produced.

Get started

NullReport gives you this structure out of the box: the default sections above, a finding library, a CVSS calculator, and DOCX export from your own template, all self-hosted so client data never leaves your machine. The free tier covers the full reporting workflow with no time limit and no card.