Report

One document. Two readers.

Every engagement ends with one report that your leadership and your engineers can both use. This page walks through its structure with an illustrative example — it is not client data.

Readers
Leadership
and engineers
Retest
Appended to
the same report
Format
[REPORT FORMAT]
Handling
[CONFIDENTIALITY & RETENTION]

Six parts, always in the same order.

  1. 01

    Executive summary

    What was tested, what was found and what it means for the business — in plain language, on one page.

  2. 02

    Scope & methodology

    Exactly which targets were in scope, when testing ran, and how it was done.

  3. 03

    Findings summary

    Every finding on one table, rated by real business risk, with its current status.

  4. 04

    Detailed findings

    For each finding: description, impact, evidence, reproduction steps and a specific fix.

  5. 05

    Remediation roadmap

    What to fix now, what can follow, and what may be an acceptable risk.

  6. 06

    Retest results

    After you patch, each finding is tested again and the result is appended to the same report.

What leadership reads first.

Illustrative / not client data

Testing of the customer platform found one critical issue: any logged-in user could read every other customer's orders. It and the high-risk password-reset issue were fixed and confirmed on retest. One medium issue is in progress; one low issue was accepted as a risk.

Critical
1
High
1
Medium
1
Low
1
Penetration test report
Illustrative / not client data
Findings summary — illustrative
ID / FindingSeverityStatus
F-01Any user can read other customers' orders via the APICriticalFixed · retested
F-02Password reset link stays valid after useHighFixed · retested
F-03No rate limit on the login formMediumIn progress
F-04Error pages reveal internal stack tracesLowAccepted risk

What engineers get for every finding.

F-01 · Illustrative

Any user can read other customers' orders via the API

Severity
Critical
Affected
GET /api/orders/{id}
Status
Fixed · retested

Description

The orders endpoint returns an order for any ID it is given. It checks that the caller is logged in, but not that the order belongs to them.

Impact

Any registered user can read every customer's orders, including names, delivery addresses and order history, by changing a number in the request.

Evidence

GET /api/orders/10482 HTTP/1.1
Host: shop.example.com
Authorization: Bearer <token of user B>
HTTP/1.1 200 OK
Content-Type: application/json

{ "id": 10482, "customer": "user A", "address": "[redacted]", "items": [ … ] }

Reproduction

  1. Log in as user A and place an order; note its ID.
  2. Log in as user B in a separate session.
  3. Request user A's order ID with user B's token.
  4. The API returns user A's order instead of 403 Forbidden.

Remediation

Check ownership on the server for every object request: load the order only where its owner matches the authenticated user, and return 404 otherwise. Apply the same check to every endpoint that takes an object ID.

Retest

Fixed · retested. The endpoint now returns 404 for orders that belong to another user.

What to fix, in what order.

  1. 01

    Fix now

    • F-01Any user can read other customers' orders via the API
    • F-02Password reset link stays valid after use
  2. 02

    Fix next

    • F-03No rate limit on the login form
  3. 03

    Decide

    • F-04Error pages reveal internal stack traces