How to write a pentest report (with an OSCP template)
Structure of a professional pentest report, how to take notes, which screenshots you need and how to build the OSCP PDF with Markdown and Pandoc.
The report is the only thing a pentest client sees and the only thing OffSec grades from your exam. You can compromise every machine and fail on the report: if a screenshot is missing or a step cannot be reproduced, those points do not count. This guide explains what goes into a good report, how to take notes so writing it is copy and paste, and how to turn Markdown into a clean PDF.
What a report has to achieve
Two different people read it and it has to work for both:
- Management wants to know, on one page and without jargon, what the risk is and what to do first.
- The technical team wants to reproduce every issue and know exactly how to fix it.
That is why every professional report has the same shape: a short executive summary and then one finding per section with steps anyone can repeat.
The structure
| Section | What it contains |
|---|---|
| Cover | Client, dates, document version and classification (confidential) |
| Executive summary | 3-5 paragraphs: scope, overall result, the most serious risks and the 3 priority recommendations |
| Scope and methodology | IPs or domains in and out of scope, dates, type of test (black box, assumed breach...) and phases followed |
| Findings summary | Table with each issue, its severity and the affected host |
| Detailed findings | One per section (see below) |
| Appendices | Credentials found, uploaded files that must be removed, full tool output |
How to write a finding
Every finding answers the same questions, always in the same order:
### 3.2 SQL injection in the `id` parameter of /products.php
**Severity:** Critical (CVSS 3.1: 9.8)
**Affected host:** 10.10.10.5 (web01)
**Description.** The `id` parameter is concatenated into a SQL query
without parameterisation, which allows reading the whole database.
**Impact.** An unauthenticated attacker obtains the hashes of every
application user, including the administrator.
**Steps to reproduce.**
1. Open `http://10.10.10.5/products.php?id=1'` → MySQL error (figure 4).
2. Run: `sqlmap -u "http://10.10.10.5/products.php?id=1" --dump -T users`
3. Result: `users` table with 12 hashes (figure 5).
**Recommendation.** Use prepared statements for every query and review
the rest of the application's parameters.
**References.** OWASP: SQL Injection Prevention Cheat Sheet.
Three rules that make the difference:
- Copyable commands. The exact command you ran, with its parameters, in a code block. Never "sqlmap was used".
- One screenshot per important step, with the IP or host name visible, numbered so you can cite it in the text.
- Concrete recommendations. "Apply patch KB5005033" helps; "improve security" does not.
For severity, use the NVD CVSS 3.1 calculator or a simple scale (critical, high, medium, low, informational) that you explain in the methodology.
Taking notes during the test (or the exam)
The report is written while you attack, not afterwards. If you do not write a command down at 3 a.m., you will not remember it at 10.
- One folder per machine, with tool output saved to files (
nmap -oA,tee). The nmap guide explains it. - One note per machine (Obsidian, CherryTree, Joplin or a
.md) with these sections: ports, enumeration, initial access, privilege escalation, credentials and flags. - Log the terminal so nothing gets lost:
script -a -f ~/exam/terminal.logat the start of each session. - Take the screenshot the moment you get something: the shell, the
whoamiand the flag contents in the same image.
In the OSCP exam the screenshot of each flag must show the contents of local.txt or proof.txt and the machine's IP, from an interactive shell on the target:
# Linux
hostname && whoami && cat /root/proof.txt && ip a
# Windows
hostname; whoami; type C:\Users\Administrator\Desktop\proof.txt; ipconfig
Warning
A flag shown through a web shell or read without an interactive shell may not be valid. Always check the rules in OffSec's exam guide before you start: they change from time to time and they are what counts.
From Markdown to PDF with Pandoc
Writing in Word with screenshots is slow. The most comfortable option is to write the report in Markdown and convert it to PDF. You need Pandoc, LaTeX and the Eisvogel template:
sudo apt install pandoc texlive-latex-recommended texlive-latex-extra texlive-fonts-extra
mkdir -p ~/.local/share/pandoc/templates
# Download the latest .tar.gz from
# https://github.com/Wandmalfarbe/pandoc-latex-template/releases and, in your downloads folder:
tar -xzf Eisvogel*.tar.gz
find . -name eisvogel.latex -exec cp {} ~/.local/share/pandoc/templates/ \;
Put this header at the top of report.md:
---
title: "Penetration Test Report"
author: ["[email protected]", "OSID: OS-XXXXX"]
date: "2026-11-03"
lang: "en"
titlepage: true
toc: true
toc-own-page: true
---
And build the PDF:
pandoc report.md -o OSCP-OS-XXXXX-Exam-Report.pdf \
--from markdown --template eisvogel --listings --number-sections
Images go in as  and the text in brackets becomes the caption.
Tip
noraj's OSCP-Exam-Report-Template-Markdown repository has ready-made exam templates with this structure. Write a test report for an HTB box before the exam: that way you hit the Pandoc problems with time to spare.
Submitting the OSCP report
After the exam you have 24 hours to submit the report. Check what the official guide asks for at that moment; usually:
- A PDF named
OSCP-OS-XXXXX-Exam-Report.pdf(your OSID). - Compressed as a
.7zwith no password and the same name:7z a OSCP-OS-XXXXX-Exam-Report.7z OSCP-OS-XXXXX-Exam-Report.pdf. - Uploaded on OffSec's submission site, checking the MD5 it shows you:
md5sum OSCP-OS-XXXXX-Exam-Report.7z.
Common errors
- Steps that cannot be repeated: an intermediate command is missing (a
chmod, annclistener). Ask someone to follow your steps or repeat them yourself on an HTB box. - Unreadable screenshots: crop to the terminal and use a large font. A full 4K screenshot is unreadable in a PDF.
- Unexplained exploits: if you modified a public exploit, say where you got it (Exploit-DB link) and which lines you changed. The guide on how to exploit a public CVE covers it.
- Sensitive data left uncensored in a real report: clear-text passwords of real users are partially masked (
Ve***23). - Leaving it for the end: write each finding as soon as you confirm it. The last hours of the exam are not for writing.
What next
Practise the full cycle with the HTB machines to prepare for the OSCP: solve one on your own and write its finding with the template above. The Zero to OSCP path ends with a mock exam where the report is part of the exercise.