{"id":7062,"date":"2026-10-29T10:30:00","date_gmt":"2026-10-29T10:30:00","guid":{"rendered":"https:\/\/krylosecurity.com\/blog\/?p=5023"},"modified":"2026-10-27T14:36:39","modified_gmt":"2026-10-27T14:36:39","slug":"penetration-test-report-example","status":"publish","type":"post","link":"https:\/\/krylosecurity.com\/blog\/penetration-test-report-example\/","title":{"rendered":"Penetration Test Report Example: What a Good Pentest Report Contains"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The report is the only part of a penetration test most people in your company will ever see. Developers fix from it, managers budget from it, and auditors and customers judge your security by it. A test can be excellent and still fail if the report is vague.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide walks through a penetration test report section by section, shows a redacted sample finding, and gives you a checklist for judging any report, whether you are reading one now or choosing a provider.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The sections of a penetration test report<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A good report has two audiences: people who decide, and people who fix. It serves both without making either read the other&#8217;s part.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"2400\" height=\"938\" src=\"https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1.jpg\" alt=\"The sections of a penetration test report, from executive summary to appendices\" class=\"wp-image-7100\" srcset=\"https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1.jpg 2400w, https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1-300x117.jpg 300w, https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1-1024x400.jpg 1024w, https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1-768x300.jpg 768w, https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1-1536x600.jpg 1536w, https:\/\/krylosecurity.com\/blog\/wp-content\/uploads\/2026\/10\/penetration-test-report-example-sections-1-2048x800.jpg 2048w\" sizes=\"(max-width: 2400px) 100vw, 2400px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">1. Executive summary<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">One or two pages, in plain language. It should answer four questions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>What was tested, and when?<\/li>\n\n\n\n<li>How exposed are we overall?<\/li>\n\n\n\n<li>What are the few issues that matter most, and what could an attacker do with them?<\/li>\n\n\n\n<li>What should we do first?<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A sentence like &#8220;an attacker with a free customer account could download other customers&#8217; invoices&#8221; is worth more than a chart of severity counts. The best summaries name business impact, not vulnerability classes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Scope and approach<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is the section auditors read first. It should state:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the exact targets: domains, IP ranges, applications, API endpoints, app builds,<\/li>\n\n\n\n<li>what was out of scope,<\/li>\n\n\n\n<li>the testing dates and environment (staging or production),<\/li>\n\n\n\n<li>the approach: black box, grey box or white box, and which accounts were provided,<\/li>\n\n\n\n<li>the standards followed, such as OWASP WSTG, the OWASP API Top 10, PTES or NIST SP 800-115,<\/li>\n\n\n\n<li>any limitations, such as a feature that was down during testing.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If the scope is vague, the report is weak evidence, however good the findings are.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Findings summary<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A table of every finding with its ID, title, severity and status. Severities are usually based on CVSS, sometimes adjusted for your environment. Read our guide to <a href=\"https:\/\/krylosecurity.com\/blog\/cvss-score-explained\/\">CVSS scores<\/a> if the numbers look arbitrary.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Detailed findings<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The core of the report. Each finding should be self-contained, so it can be pasted into a ticket and fixed by someone who never read the rest. A complete finding has:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>title<\/strong> that says what is wrong in plain words,<\/li>\n\n\n\n<li><strong>severity<\/strong> with the scoring behind it,<\/li>\n\n\n\n<li><strong>affected asset<\/strong>: the exact URL, endpoint, host or app screen,<\/li>\n\n\n\n<li><strong>description<\/strong> of the weakness,<\/li>\n\n\n\n<li><strong>impact<\/strong>: what an attacker could actually do, in business terms,<\/li>\n\n\n\n<li><strong>steps to reproduce<\/strong>, so your team can confirm it and later confirm the fix,<\/li>\n\n\n\n<li><strong>evidence<\/strong>: requests and responses or screenshots, with sensitive data redacted,<\/li>\n\n\n\n<li><strong>remediation<\/strong>: a fix written for your stack, not a generic link,<\/li>\n\n\n\n<li><strong>references<\/strong>, such as the OWASP category or CWE.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5. Positive observations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">What held up. If the tester could not break your MFA or your file upload handling, say so. It tells you which controls are earning their keep.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Appendices<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tools used, the list of hosts or endpoints tested, and any raw data that supports the findings without cluttering them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A sample finding<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is what one finding looks like when it is written well. The details are illustrative and redacted.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>KS-04: Customers can download other customers&#8217; statements<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Severity:<\/strong> High (CVSS 4.0: 8.7)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Affected asset:<\/strong> <code>GET \/api\/v2\/statements\/{statementId}\/download<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Description:<\/strong> The endpoint returns a statement for any ID it receives. It checks that the caller is signed in, but not that the statement belongs to them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Impact:<\/strong> Any customer can download any other customer&#8217;s monthly statements, which include names, addresses, account numbers and transactions. Statement IDs are sequential, so all of them can be collected with a simple script.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Steps to reproduce:<\/strong> Sign in as test user A and download one of A&#8217;s statements, noting its ID. Sign in as test user B and request A&#8217;s statement ID. The statement is returned with HTTP 200.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Remediation:<\/strong> On the server, look up the statement together with the signed-in customer&#8217;s ID and return 404 if they do not match. Apply the same check to every endpoint that takes an object ID. Consider non-sequential identifiers as a second layer, not a replacement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Reference:<\/strong> OWASP API Security Top 10, API1:2023 Broken Object Level Authorization<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Notice what it avoids: no scanner jargon, no &#8220;may allow&#8221;, no copy-pasted paragraph about IDOR in general. A developer can fix it in an afternoon, and a manager can understand why it matters. For more on this class of bug, see our guide to <a href=\"https:\/\/krylosecurity.com\/blog\/broken-access-control-examples\/\">broken access control examples<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Checklist: is this a good report?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use this when you receive a report, or ask a provider for a sample before you buy one:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The executive summary names business impact, with counts as support.<\/li>\n\n\n\n<li>The scope lists exact targets, dates and approach.<\/li>\n\n\n\n<li>Every finding has steps to reproduce and evidence.<\/li>\n\n\n\n<li>Remediation is specific to your technology.<\/li>\n\n\n\n<li>Each severity comes with the reasoning behind it.<\/li>\n\n\n\n<li>There is no unverified scanner output padding the findings.<\/li>\n\n\n\n<li>Sensitive data in the evidence is redacted.<\/li>\n\n\n\n<li>Critical issues were reported to you during testing, not first in the report.<\/li>\n\n\n\n<li>A retest report is available once you have fixed the issues.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What auditors and customers look for<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the report is going to a SOC 2 auditor, a PCI assessor or a customer&#8217;s security team, they will check three things before reading a single finding:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Independence.<\/strong> The testers did not build or run the systems they tested.<\/li>\n\n\n\n<li><strong>Scope match.<\/strong> The scope covers the systems in their audit boundary or contract.<\/li>\n\n\n\n<li><strong>Remediation evidence.<\/strong> High and critical findings were fixed and retested, or have a documented plan.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Our page on <a href=\"https:\/\/krylosecurity.com\/compliance-penetration-testing\">penetration testing for compliance<\/a> covers what each framework expects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Can I get a penetration test report template?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The structure above is the template: executive summary, scope and approach, findings summary, detailed findings, positive observations and appendices. What makes a report good is the quality of each finding, which a template cannot give you.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Should we share the full report with customers?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Usually not. Share an attestation letter or the executive summary and scope, under NDA. The detailed findings are a guide to your weaknesses, so keep them inside the team that fixes them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How long after testing should the report arrive?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Most providers deliver within one to two weeks of testing ending. Critical issues should reach you during testing, not in the report.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is a VAPT report?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The same thing under a different name. VAPT stands for vulnerability assessment and penetration testing, and the report covers both the scanning and the manual testing. See <a href=\"https:\/\/krylosecurity.com\/blog\/vulnerability-assessment-vs-penetration-testing\/\">vulnerability assessment vs penetration testing<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">See our reports for yourself<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every Krylo Security report follows this structure, and every finding in it has been reproduced by a tester. <a href=\"https:\/\/krylosecurity.com\/contact\">Ask us what your report will include<\/a> when you book your scoping call, or read how we run the <a href=\"https:\/\/krylosecurity.com\/penetration-testing-process\">whole process<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A walk through a penetration test report, section by section, with a redacted sample finding. Use it to judge a report you have received, or to know what to ask for before you buy.<\/p>\n","protected":false},"author":1,"featured_media":6023,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44],"tags":[94,92,6,93],"class_list":["post-7062","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-penetration-testing","tag-executive-summary","tag-penetration-test-report","tag-penetration-testing","tag-vapt-report"],"_links":{"self":[{"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/posts\/7062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/comments?post=7062"}],"version-history":[{"count":1,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/posts\/7062\/revisions"}],"predecessor-version":[{"id":7101,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/posts\/7062\/revisions\/7101"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/media\/6023"}],"wp:attachment":[{"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/media?parent=7062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/categories?post=7062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/krylosecurity.com\/blog\/wp-json\/wp\/v2\/tags?post=7062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}