Skip to main content
Vexaro SecuritySample report
Sample report

What our assessment report looks like

A redacted, illustrative excerpt of the deliverable you receive at the end of an engagement. Every finding below is synthetic and relates to a fictional target. No real client data appears here.

Engagement
Web application & API penetration test
Target
Acme Cloud Platform (illustrative)
Assessment window
A two-week engagement (relative, no fixed dates)
Classification
Confidential (illustrative sample)
Report version
Sample v1.0

Executive summary

Vexaro assessed the externally reachable web application and supporting API of the Acme Cloud Platform over a two-week, grey-box engagement. Testing followed the OWASP Web Security Testing Guide and was verified manually beyond automated tooling.

Overall risk posture: elevated. The application enforces authentication and transport security correctly, but authorisation is applied inconsistently at the object level. Two findings can each be exploited on their own: an insecure direct object reference on the billing API and a server-side request forgery in the document-import feature. Chained together, they would let an authenticated low-privilege user read other tenants' invoices and reach internal cloud metadata. Fixing the access-control layer and restricting outbound fetches removes most of the remaining risk.

Findings by severity
0
Critical
2
High
2
Medium
2
Low
2
Info

8 findings, scored with CVSS 3.1

Scope & methodology

The engagement covered the production web application, its REST API, the cloud account hosting them and the externally reachable network perimeter. Testing was time-boxed and conducted from an authenticated low-privilege account plus an unauthenticated baseline.

In scope
  • Web application: app.acme.example (authenticated and anonymous flows)
  • REST API: api.acme.example (v1 and v2 endpoints)
  • Cloud account: object storage, compute metadata and IAM review
  • External network perimeter: exposed services and TLS configuration
Out of scope
  • Denial-of-service and volumetric load testing
  • Social engineering and physical access
  • Third-party SaaS not operated by the target

Methodology & references

Testing was manual-first and mapped to recognised industry frameworks so findings are reproducible and the coverage is auditable.

OWASP WSTG

Web Security Testing Guide: the test cases behind application coverage.

OWASP ASVS

Application Security Verification Standard: the control-level verification baseline.

MITRE ATT&CK

Adversary tactics and techniques used to frame realistic attack paths.

PTES

Penetration Testing Execution Standard: the overall engagement process.

How we rate severity

Each finding is scored with CVSS 3.1 and translated into a business-risk rating. Severity reflects exploitability and impact in the context of this environment, not the base score alone.

Findings

Eight representative findings from the engagement, ordered by severity. The first is expanded in full below to show the level of detail in every report entry.

IDFindingSeverityCVSSStatus
ACME-2024-001IDOR on billing API exposes other tenants' invoicesHigh8.1Open
ACME-2024-002Server-side request forgery in document importHigh7.7Open
ACME-2024-003Broken function-level authorisation on admin endpointsMedium6.5Fixed and retested
ACME-2024-004Stored XSS in the support-ticket subject fieldMedium5.4Open
ACME-2024-005Weak password policy permits trivial credentialsLow3.7Open
ACME-2024-006Verbose API errors leak stack traces and library versionsLow3.1Risk accepted
ACME-2024-007Missing security headers (HSTS, CSP, frame-ancestors)Info2.4Fixed and retested
ACME-2024-008Session cookie issued without the Secure attributeInfo2.0Open

Sample finding in full

One finding, expanded to the depth every entry gets in a real report: description, impact, evidence, reproduction, remediation and references.

ACME-2024-001HighCVSS 3.1 8.1 (High)

IDOR on billing API exposes other tenants' invoices

Finding ID
ACME-2024-001
CVSS 3.1
8.1 (High)
Vector
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
CWE
CWE-639: Authorization Bypass Through User-Controlled Key

Description

The billing API returns invoice documents by a sequential numeric identifier supplied in the request path. The endpoint authenticates the caller but never checks that the requested invoice belongs to the caller's tenant. Any authenticated user can therefore enumerate the identifier and retrieve invoices belonging to other organisations, including billing contact names, amounts and line items.

Impact

This is a cross-tenant confidentiality breach. An authenticated low-privilege user from any tenant can read the financial records of every other tenant by incrementing a single integer. The exposed data includes commercial terms and personal contact details, creating both a privacy and a competitive-intelligence exposure. Because identifiers are sequential, the entire invoice corpus can be scraped programmatically in minutes.

Evidence

Illustrative request and response. The host, token and values are synthetic and redacted.

Request: an invoice that belongs to another tenant
GET /v2/invoices/10428 HTTP/1.1
Host: api.acme.example
Authorization: Bearer eyJhbGciOi...REDACTED.SAMPLE.TOKEN
Accept: application/json
Response: 200 OK (the caller is tenant 7781, the invoice belongs to tenant 3304)
HTTP/1.1 200 OK
Content-Type: application/json
{
  "invoice_id": 10428,
  "tenant_id": 3304,
  "bill_to": "[REDACTED], Northwind Trading",
  "amount_due": "14,920.00 USD",
  "status": "unpaid"
}'

Steps to reproduce

  1. 1Authenticate to the application with any valid low-privilege account and capture the bearer token.
  2. 2Request your own invoice, e.g. GET /v2/invoices/10427, and confirm a 200 response.
  3. 3Decrement or increment the numeric identifier (.../10428, .../10429) and replay the request with your own token.
  4. 4Observe that invoices belonging to other tenant_id values are returned, confirming the missing object-level authorisation check.

Remediation

Enforce object-level authorisation on every request: resolve the invoice, then confirm its tenant_id matches the authenticated principal's tenant before returning any data, otherwise respond 404. Apply the check centrally (for example in a policy layer or query scope) rather than per-handler, and add a regression test that asserts a cross-tenant request is rejected. Replacing sequential identifiers with unguessable ones reduces enumeration but is defence-in-depth, not a substitute for the authorisation check.

Want a report like this for your systems?.

Tell us what you'd like us to test. We'll scope the engagement, agree the rules with you and deliver a report of the same depth under NDA. The first consultation is free.