A pentest report is the deliverable that remains once the testers leave. The exploits, the late-night shells and the clever chains only matter if they end up in a document that executives understand, developers can act on and auditors accept as evidence. A weak report turns a good penetration test into a PDF nobody reads.
This guide gives you a complete pentest report template you can copy, explains what goes in each section, walks through a fully written example finding and closes with tips for writing the same report for two very different readers: executives and developers.
What a penetration testing report is for
A penetration test is an authorized, time-boxed attack against a defined scope. The report has four jobs:
- Inform decisions. Leadership needs to know how exposed the company is and what it costs to fix.
- Enable fixes. Engineers need enough detail to reproduce every issue without calling the tester.
- Provide evidence. Customers, auditors and frameworks such as SOC 2, ISO 27001 or PCI DSS often ask for a recent report and proof of remediation.
- Create a baseline. Next year's test should be compared against this one.
If a section of your report does not serve one of those jobs, cut it. Long lists of tool output pasted as appendices rarely help anyone.
The structure of a good pentest report
| Section | Main reader | What it answers |
|---|---|---|
| Executive summary | CEO, CTO, board, customers | How bad is it, what matters most, what should we do |
| Scope and rules of engagement | Everyone, auditors | What was tested, when, from where, and what was excluded |
| Methodology | Security team, auditors | How the test was performed and against which standard |
| Findings summary | Engineering leads | The full list, ranked by severity |
| Detailed findings | Developers | How to reproduce, why it matters, how to fix |
| Risk rating | Leadership, security | Overall posture in one sentence |
| Retest | Auditors, customers | What was verified as fixed and when |
Free pentest report template (copy and paste)
Copy the block below into your document editor or Markdown repository and replace the placeholders in brackets.
PENETRATION TEST REPORT
Client: [Company name]
Application / environment: [Name, version, URL or repository]
Test window: [Start date] to [End date]
Report version: [1.0] Date: [Date] Classification: [Confidential]
Prepared by: [Tester name, certifications] Reviewed by: [QA reviewer]
1. EXECUTIVE SUMMARY
1.1 Objective: [Why the test was performed: customer requirement, release, audit]
1.2 Overall risk rating: [Critical / High / Medium / Low]
1.3 Key results:
- [N] findings: [x] Critical, [x] High, [x] Medium, [x] Low, [x] Informational
- Most important risk: [One sentence in business terms]
- Strengths observed: [What was done well]
1.4 Top recommendations:
1. [Action, owner, suggested deadline]
2. [Action, owner, suggested deadline]
3. [Action, owner, suggested deadline]
2. SCOPE AND RULES OF ENGAGEMENT
2.1 In scope: [URLs, IP ranges, APIs, repositories, mobile apps]
2.2 Out of scope: [Third-party services, production data changes, DoS]
2.3 Test type: [Black box / grey box / white box]
2.4 Accounts provided: [Roles and number of test users]
2.5 Source IP addresses of testers: [IPs]
2.6 Constraints and limitations: [Time, unavailable features, blocked tests]
3. METHODOLOGY
3.1 Standards followed: [PTES, OWASP WSTG, NIST SP 800-115]
3.2 Phases: reconnaissance, mapping, vulnerability discovery,
exploitation, post-exploitation, reporting
3.3 Tools used: [List]
3.4 Severity model: CVSS [v3.1 / v4.0] base score plus business context
None 0.0 | Low 0.1-3.9 | Medium 4.0-6.9 | High 7.0-8.9 | Critical 9.0-10.0
4. FINDINGS SUMMARY
| ID | Title | Severity | CVSS | CWE | Asset | Status |
|--------|-------------------------|----------|------|---------|----------------|--------|
| PT-01 | [Title] | [High] | [x.x]| [CWE-x] | [Endpoint/file]| Open |
| PT-02 | [Title] | [Medium] | [x.x]| [CWE-x] | [Endpoint/file]| Open |
5. DETAILED FINDINGS
ID: [PT-01]
Title: [Short, specific title]
Severity: [High] CVSS: [score] ([vector]) CWE: [CWE-x: name]
Affected asset: [URL, parameter, file and line]
Description: [What the vulnerability is]
Steps to reproduce:
1. [Step]
2. [Step]
Evidence: [Request/response, screenshot reference, redacted data]
Impact: [What an attacker can do, in business terms]
Remediation: [Specific fix, with code or configuration example]
References: [OWASP, CWE, vendor docs]
Status: [Open / Fixed / Risk accepted]
6. OVERALL RISK RATING
[Rating] because [main reasons]. Likelihood: [x]. Impact: [x].
7. RETEST
Retest date: [Date]
| ID | Original severity | Retest result | Evidence |
|-------|-------------------|-----------------|-----------------|
| PT-01 | High | Fixed | [Reference] |
| PT-02 | Medium | Partially fixed | [Reference] |
APPENDIX
A. Test accounts and data created (and cleaned up)
B. Glossary of terms for non-technical readersSection by section: what to write
Executive summary
One page, maximum. No payloads, no HTTP headers. State the objective, the overall rating, the count of findings by severity, the one or two risks that actually matter in business language and the top three actions. "An authenticated customer can download any other customer's invoices, which exposes names, addresses and billing amounts" beats "IDOR in invoice API".
Scope and rules of engagement
This is the section that protects both parties. List exactly what was tested and what was not, the dates, the test type (black, grey or white box) and any limitation. If the admin panel was down for two of the five days, write it. An auditor who reads "full application tested" when half of it was unreachable will not trust the rest.
Methodology
Name the standard you followed: PTES (Penetration Testing Execution Standard), the OWASP Web Security Testing Guide (WSTG) or NIST SP 800-115. Mapping findings to the OWASP Top 10 also helps readers place each issue. List the main tools, but remember the report is about results, not a catalog of penetration testing tools.
Findings: severity, CVSS and CWE
Every finding needs a severity that readers can compare. The common choice is CVSS, the Common Vulnerability Scoring System maintained by FIRST. CVSS v4.0 was published on November 1, 2023, and v3.1 is still widely used. Both share the same qualitative bands: None 0.0, Low 0.1 to 3.9, Medium 4.0 to 6.9, High 7.0 to 8.9, Critical 9.0 to 10.0. Always state the version and the full vector, not just the number, so anyone can recompute it.
Add a CWE identifier (Common Weakness Enumeration, maintained by MITRE). CWE tells developers the class of bug, links to prevention guidance and lets you track recurring weaknesses across reports.
Risk rating and retest
The overall risk rating is a judgment, not an average. One Critical finding in an internet-facing payment flow makes the overall rating Critical even if everything else is Low. The retest section records, for each finding, whether the fix was verified, with date and evidence. Customers who ask for "your latest pentest" almost always want this section.
Example finding, fully written
Here is how a complete finding looks in practice. It is an IDOR vulnerability, one of the most common issues in modern web apps and APIs.
ID: PT-03
Title: Any authenticated user can read other customers' invoices
Severity: Medium
CVSS v3.1: 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)
CWE: CWE-639 Authorization Bypass Through User-Controlled Key
Affected asset: GET /api/invoices/:id
src/routes/invoices.js, line 42
Description:
The endpoint loads an invoice by its numeric ID and returns it to
any logged-in user. It does not check that the invoice belongs to
the account making the request.
Steps to reproduce:
1. Log in as user A (tenant 101) and open invoice 5120.
2. Replay the request changing the ID to 5121.
3. The API returns HTTP 200 with the invoice of tenant 205.
Evidence:
GET /api/invoices/5121 HTTP/1.1
Authorization: Bearer <token of user A>
HTTP/1.1 200 OK
{"id":5121,"tenant_id":205,"customer":"[REDACTED]","total":"[REDACTED]"}
Impact:
Invoice IDs are sequential, so an attacker with a free account can
download every invoice in the platform: customer names, addresses
and amounts. This is a personal data breach under most privacy laws.
Remediation:
Scope the query to the current tenant and return 404 when the
invoice does not belong to it:
const invoice = await Invoice.findOne({
where: { id: req.params.id, tenantId: req.user.tenantId }
});
if (!invoice) return res.status(404).end();
Add an automated test that requests another tenant's invoice and
expects 404. Apply the same check to PUT and DELETE on this route.
References: OWASP WSTG Authorization Testing, CWE-639
Status: OpenNotice the details that make this finding useful: a title a CEO understands, the exact file and line, a reproducible request, redacted evidence, impact in business terms and a fix a developer can paste. Note also that the CVSS score is only Medium while the business impact is serious. That is why the executive summary may still list it as a top priority. Say so explicitly instead of silently inflating the score.
Writing for executives vs developers
For executives
- Lead with the conclusion. The first sentence says the overall risk and the single most important issue.
- Translate impact. Talk about customer data, money, downtime, contracts and compliance, not about parameters and payloads.
- Give decisions, not lists. Three prioritized actions with an owner and a timeline are more useful than twenty findings.
- Be honest about limits. Say what was not tested. A clean report on a narrow scope is not a clean bill of health.
- Avoid fear. Calm, factual language builds more trust than red banners.
For developers
- Make every finding reproducible. Exact request, account role, environment and expected versus actual response.
- Point to code when you can. In a white-box or code security audit, file and line save hours.
- Propose a concrete fix in their stack, and suggest a regression test so the bug does not come back.
- Group related issues. If twelve endpoints miss the same ownership check, report one root cause with the full list of affected routes.
- Redact sensitive data in screenshots and responses. The report itself will be emailed around.
Common mistakes in pentest reports
- Pasting scanner output as findings. Unverified scanner results belong in an appendix, if anywhere. If you want the automated layer, run open source vulnerability scanners before the test, not inside the report.
- Severity without a vector. "High" with no CVSS vector cannot be challenged or verified.
- Generic remediation. "Validate input" is not a fix. Show the change.
- No retest. A report without verified remediation is only half the evidence customers want.
- Missing scope limits. Silence about what was not tested is read as "everything was tested".
Continuous testing between pentest reports
A manual pentest report is a snapshot. Your code changes every week, so many teams complement the annual report with continuous testing of the code itself. With Nurbak, for example, you connect GitHub and scan a repository: its own self-hosted AI model analyzes the code (the analysis does not send your code to OpenAI or Anthropic) and reports exploitable vulnerabilities with file and line, dependency CVEs, GitHub Actions, Docker, Terraform and Kubernetes misconfigurations and secrets in git history, with a 0 to 100 score and plain-language explanations. It can also open a Pull Request with the fix plus a security regression test (the fix uses Claude, only with your explicit consent). See how it works on the AI pentest page.
That does not replace a human tester for business logic and chained attacks. If you are choosing one, read our guide to penetration testing companies and ask every vendor for a sample report before signing.
Bottom line
A useful pentest report is short at the top and precise at the bottom: a one-page executive summary, a clear scope, a named methodology, findings with CVSS vector, CWE, evidence and a concrete fix, an honest overall rating and a retest. Copy the template above, adapt it to your context and keep each section written for its own reader. When you want to find issues before the next test, start with an AI pentest of your repository.
