Skip to content
Paul Marinos
Menu

Report Writeups

The report is the deliverable — finding structure that gets things fixed, severity you can defend, and writing for the developer who has to do the work.

The report is the product. The testing is what you did; the report is what the client receives, and a critical finding that the developer can’t reproduce or won’t prioritise has the same real-world effect as a finding you never made. Testing skill gets you the vulnerability. Writing skill gets it fixed.

This is intelligence report writing in a specific dialect — same discipline of BLUF, calibrated confidence and a clear “so what”, pointed at a different reader.

A working structure, roughly in reading order:

  1. Executive summary — the BLUF. What was tested, what was found, what it means to the business, in language a non-technical executive acts on. Most of the report’s decisions are made here or not at all.
  2. Scope and methodology — what was and wasn’t in scope, and how you tested. This is where you protect the client from reading “no findings” as “secure”: absence of findings in an area you couldn’t reach is not assurance.
  3. Findings — the substance, ordered by severity.
  4. Appendices — raw output, full request/response pairs, supporting detail for anyone verifying.

The executive summary and the findings serve different readers and should each stand alone. An executive will never read a finding; a developer will never rely on the summary.

Every finding, the same shape, so a reader can navigate on autopilot:

  • Description — what the flaw is, plainly.
  • Impact — what it lets an attacker do to this organization. Not generic; concrete.
  • Evidence — proof it is real: the request, the response, the screenshot.
  • Reproduction — exact steps to see it again. This is what gets it fixed, and what gets skipped under time pressure.
  • Remediation — how to resolve it, specific enough to action, with a link to the underlying secure-coding control.

Reproduction is the highest-value and most-neglected section. A developer who can reproduce a bug in two minutes fixes it; one who cannot, disputes it. Write the steps as if for someone with access but no context.

The difference between a finding that gets fixed and one that gets filed is almost always the impact statement. Weak impact describes the vulnerability class; strong impact describes the consequence to this client.

Weak: “SQL injection was identified in the search parameter.”

Strong: “The search parameter is vulnerable to SQL injection, allowing extraction of the full customer table — 2.3 million records including hashed passwords and email addresses — by an unauthenticated user.”

Same bug. The second is impossible to deprioritise, because it names what is lost. This is the “so what”, and it is the same skill that separates intelligence that changes a decision from intelligence that gets filed.

Severity drives remediation priority, so it will be argued — usually downward. Justify it rather than asserting it, against a stated model (CVSS with environmental context, or the risk-prioritization inputs: exploitability, exposure, and business consequence).

Two disciplines keep severity credible. Rate by realistic impact in context — a critical CVSS on an unreachable internal service may be a medium here, and saying so protects your credibility on the findings that are genuinely critical. And don’t inflate: a report where everything is high is a report where nothing is, and the client learns to discount you.

  • Redact secrets in screenshots — the report itself becomes sensitive, and a report leaking credentials is its own incident.
  • Timestamp actions, so the client can correlate against their logs — which doubles as a detection check: did any of it alert.
  • Capture enough to reproduce, not the entire session. Relevant and clear beats exhaustive.
  • Treat the report as sensitive end to end — it is a map of how to compromise the client.

A finding is not closed because a report was delivered; it is closed when the fix is verified. Retest against the original reproduction steps, confirm the remediation actually resolves it rather than hiding the symptom, and watch for fixes that move the bug rather than remove it. Closure reporting — what was fixed, what remains, what was accepted as risk — is what turns an engagement into a change rather than a document.

The person who fixes the bug is usually not the person who commissioned the test, and they read differently:

  • Be specific about location — file, endpoint, parameter. “The login is vulnerable” wastes an hour they’ll resent.
  • Explain the why, briefly. A developer who understands the class fixes it correctly and avoids re-introducing it; one handed a patch to apply does not.
  • Respect their constraints. “Rewrite in a memory-safe language” is not remediation.
  • Skip the condescension. The bug is a mistake, not a character flaw, and the report is read by the person who made it.

This is intelligence report writing applied — BLUF, confidence, the “so what”. Every remediation points back to an AppSec control. Severity leans on risk prioritization. And the timeline doubles as input to detection: what fired, and what should have.

Graph View