Sample report / fictional examples

A sample penetration testing report

This sample penetration testing report uses fictional systems to demonstrate the Balhence reporting format. Each finding explains impact, prerequisites, reproduction steps, evidence, severity reasoning, and a practical fix. It is a synthetic application example for evaluating report quality, not a client report or a compliance certificate.

  • Synthetic evidence
  • Fictional accounts
  • Not a client report
Explore the sample

Four ways to read the same finding.

Choose the summary, technical evidence, suggested fix, or illustrative re-test. Each view answers a different question.

For the release decision

One customer's account can read another customer's invoice.

HIGH

A standard user in one controlled tenant can retrieve an invoice belonging to another controlled tenant by changing an object identifier. The server confirms authentication but does not enforce object ownership.

01Valid user sessionCommon prerequisite
02Change invoice IDNo privileged access
03Cross-tenant dataConfidentiality impact
Affected surface
GET /api/v1/invoices/{id}
Required access
Standard authenticated user
Evidence boundary
Two synthetic test tenants
Priority
Before affected release
Engineer view

AUTHZ-01 | Cross-tenant invoice access

HIGH
Controlled request
GET /api/v1/invoices/inv_test_b HTTP/1.1
Host: app.example.test
Authorization: Bearer <tenant_a_test_session>
Accept: application/json
Observed response200 OK
{
  "id": "inv_test_b",
  "tenant_id": "ten_test_b",
  "status": "paid",
  "total": 42000
}

Reproduction path

  1. Authenticate as user.a@tenant-a.example.test.
  2. Request the controlled Tenant A invoice and record the normal request shape.
  3. Replace only the invoice identifier with inv_test_b, owned by controlled Tenant B.
  4. Observe that the API returns the Tenant B object instead of denying access.
Fix path

Authorize the object, not merely the route.

Root cause first
Insufficient control
invoice = invoices.find(params.id)
return invoice

The lookup trusts a client-controlled identifier after confirming only that the caller is logged in.

Required control
invoice = currentTenant.invoices.find(params.id)
authorize(user, "read", invoice)
return invoice

Resolve the object inside the authorized tenant boundary and enforce permission at the data-access layer.

Remediation acceptance criteria

  • Cross-tenant identifiers return a consistent denial or not-found response.
  • Equivalent invoice export, update, attachment, and bulk routes enforce the same boundary.
  • Authorization tests cover standard, manager, and tenant-admin roles.
  • Logs capture denied cross-boundary access without storing sensitive response data.
After the illustrative fix

What changed, and what still wasn't checked.

FIXED
Original200 OK

Tenant A session retrieved controlled Tenant B invoice.

RemediationOwnership enforcement

Object lookup constrained to the authenticated tenant.

Verification404 Not Found

Original request and adjacent controlled variants denied.

Illustrative re-test record
TestExpectedObservedStatus
Original cross-tenant readDenied404Fixed
Same-tenant readAllowed200Pass
Cross-tenant exportDenied404Fixed
Unrelated billing routesOut of re-test scopeNot testedLimited
The full sample report

Review the full 11-page PDF.

The PDF includes the test scope, methods, findings, supporting evidence, and terms for re-testing fixes.

Download PDF

Open the sample report

Your browser cannot display the PDF inline.

Download the PDF
Your application

Need a report your team can work from?

Tell us what needs testing and who will read the results. We'll agree on coverage, the handover, and any re-test before proposing the work.