The PDF report
The sections of the PDF report, in order, and what each one is built from.
The PDF is rendered once, when the report is generated, and written to a file named after the engagement. Downloading it later serves that file. It opens with the title Penetration Test Report and then renders thirteen sections, in the order below.
Sections¶
- Engagement Details. The engagement id, the framework, the targets, the test period from the run's start and completion times, the tools used, and the in-scope and out-of-scope lists. The tools used are the first word of every command recorded in the findings' evidence, not a log of what ran.
- Rules of Engagement. The rules-of-engagement document the agent rendered at the start of the run, printed as preformatted text. If none was recorded, the section says so.
- Executive Summary. Computed from the findings. The risk posture is the
highest severity present, or
informationalwhen nothing ranks aboveinfo. Headline findings are the first five in severity order. The business impact sentence counts findings by severity. Key recommendations cut every finding's remediation text to its first 80 characters and list the five most frequent results. The scope summary counts targets and scope entries. - Methodology. Fixed text, the same in every report: four standards (PTES, NIST SP 800-115, MITRE ATT&CK, OWASP WSTG), a list of seven phases under Phases Executed, and a note on how the crosswalk is filled. The phase list does not come from the run. A run that stopped in its first phase prints the same seven.
- Intelligence Summary. Short ids of the findings with severity
info, from any phase. The section also has slots for OSINT facts and public assets, which the agent's intelligence record does not fill. With noinfofindings the section reads "No intelligence gathered." - Threat Model. The assets, threat actors, attack paths and hypotheses the
agent recorded with its
record_threat_modelcall. If it made no such call, the section reads "No threat model recorded." - Test Results. One subsection per NIST SP 800-115 test category, with a fixed objective, the run's tools list when it is not empty, severity counts and the short ids of the findings in that category. Severity and taxonomy describes how the subsections are filled.
- Findings. A table of counts by severity, listing the severities present, followed by the findings. Ordering covers the order. For each finding: title and severity, CVSS score and vector when a score exists, the affected asset, the phase, the description, the content of every evidence item, the remediation, and, where present, ATT&CK technique ids, WSTG ids, CVE ids and related control ids. On a sealed run whose manifest was readable, a Sealed evidence table follows with the sequence number, kind and SHA-256 of every artifact the manifest links to the finding. A finding's status is not printed. With no findings the section reads "No vulnerabilities were discovered."
- Attack Chain. One line for every finding that lists related findings: its title, severity and technique ids, and the short ids of the related findings that belong to the same run. With none, the section reads "No attack chain reconstructed."
- Compliance Crosswalk. One row per finding: title, severity, ATT&CK ids, WSTG ids, CVE ids, and the control ids, labelled with the framework's full name.
- Control Mappings. Every control the framework declares, with its name, a status of Tested or Not Tested, and the titles of the findings mapped to it. Frameworks explains what the two statuses mean. A framework that declares no controls produces no section.
- ATT&CK Heatmap. Two tables: how many findings carry each tactic id, with the tactic's name from the ATT&CK manifest, and how many carry each technique id. With no ids at all, the section reads "No ATT&CK mappings recorded."
- Evidence Integrity. The seal record, described below.
The report does not filter findings by status. The Status section of Anatomy of a finding describes the effect.
Evidence integrity¶
A report generated by the application always has this section. What it holds depends on the run's seal.
Sealed, manifest readable. A table of eight values: chain head, manifest
SHA-256, signing key id, sealed entries, chain algorithm, signature algorithm,
sealed at, signed at. The chain head, the entry count, the algorithms, the key
id and the signing time are read from the signed manifest and signature block
rather than the database. The table is followed by a note telling the reader to
export the locker and run pentr-verify with --key, and a key-custody note
stating that the key is held in software and the timestamp is self-asserted.
Unsealed. No table. The section prints:
This run was not sealed. The evidence in this report is not independently verifiable: there is no hash chain, no manifest and no signature to check it against.
No finding has a Sealed evidence table.
Sealed, manifest unreadable. The section prints:
This run is sealed, but its manifest was not readable when this report was generated, so per-finding artifact hashes are omitted. The chain head and manifest hash below still identify the seal; verify them against an exported locker with pentr-verify.
The table follows, filled from the database's seal record, then the two notes. This case covers a manifest or signature block that is missing from the store, unreadable, not a JSON object, or lacking a field the section needs; a manifest entry that is malformed; and a seal made before signing was introduced. No finding has a Sealed evidence table.
Sealing covers when a run is sealed. The section reports what the seal record says; checking it is the job of Verifying a locker.
Ordering¶
The PDF lists findings in the order they were stored, which is the order the agent recorded them in the run. The executive summary's headline findings are sorted by severity. Every other list of findings follows stored order: the informational finding ids, the test-result ids, the findings section, the attack chain, the crosswalk and the related findings under each control. The controls follow the framework file's order, a finding's control ids and the ATT&CK heatmap are sorted by id, and the key recommendations are ordered by how many findings share them. The CSV and SARIF exports sort differently, as SARIF and CSV exports describes.
One report per engagement¶
Generating a report for an engagement that already has one returns the existing report; no new PDF is rendered. The file therefore reflects the findings and the framework file as they stood at first generation, and changes to the framework file do not reach it. The SARIF and CSV exports are rebuilt at every download and do pick such changes up.
The download serves the engagement's PDF file whichever of the engagement's report ids the request names. If the file is missing from disk, the PDF download returns 404 while the SARIF and CSV downloads still work.
Retention¶
A report record carries retention_days, 90 unless the deployment configures
another value, and an expires_at set that many days after generation. Both
are returned by the endpoint that lists an engagement's reports. Nothing else
reads them: no job deletes an expired report, and the download does not refuse
one. The console does not show either value.
Last updated 2026-09-22