The decision for the risk owner
Restore tenant isolation.
A standard user can retrieve a document assigned to another tenant in the synthetic scenario. If present in a real shared platform, that boundary failure could expose board material, transaction records or commercially sensitive information.
Contain, correct, then verify.
Restrict the affected operation while the policy is corrected. Closure requires evidence that forbidden reads fail and legitimate operations still work; a gateway rule alone does not establish that the object boundary is sound.
| Field | Assessment |
|---|---|
| Finding reference | EX-01 / AUTH-001 · synthetic application |
| Affected operation | Document retrieval in a shared enterprise workspace |
| Preconditions | Authenticated reader; two tester-controlled tenants and known fixture document identifiers |
| Security property | An actor can act only on an entitled resource, within the permitted operation and context |
| Business significance | Confidentiality of documents segregated by legal entity or client relationship |
| Risk statement | High illustrative priority; final severity depends on actual sensitivity, exposed operations and compensating controls |
Locate the missing decision.
- Identity is necessary
A valid Tenant A credential establishes the actor. It does not authorise every document.
- Observed gap
The document service looks up a Tenant B object without enforcing its access policy.
- Corrected decision
Evaluate the authenticated actor, requested action, tenant relationship and document classification on the server.
- Controlled outcome
Reject the cross-tenant request without object metadata; preserve permitted same-tenant operations.
The gateway establishes that the credential is valid and may call a document endpoint. The document service must still decide whether this actor may perform this operation on this object. The corrected design applies that decision before serialisation or any data-bearing response; background exports, batch endpoints and indirect download paths require equivalent control.
A finding another engineer can reproduce.
Use authorised, tester-owned fixtures to create a paired request record. Keep the actor, endpoint, method and relevant session context constant; change the controlled resource relationship. Record expected and observed behaviour, then preserve sufficient evidence for the application owner to reproduce the decision without circulating live credentials.
| Reference | Controlled observation | What it supports |
|---|---|---|
| AUTH-E01 | Tenant A reader requests a Tenant A document: 200 with the intended fixture. | The permitted operation works for the test identity. |
| AUTH-E02 | The same reader requests a known Tenant B fixture: 200 with Tenant B content. | The tested read operation fails to enforce the expected tenant boundary. |
| AUTH-E03 | An unauthenticated request is denied. | Authentication is present; this does not resolve object-level authorisation. |
| AUTH-E04 | Response contents are compared with the two fixture records. | The conclusion rests on the returned object, not only a status code or page title. |
Inspect the normalised request / decision excerpt
{
"example": "Synthetic fixture only",
"request": {
"method": "GET",
"host": "workspace.example.invalid",
"path": "/v1/documents/doc-B-104",
"credential": "[omitted]",
"actor": {
"tenant": "A",
"role": "reader"
}
},
"resource": {
"id": "doc-B-104",
"tenant": "B",
"classification": "confidential"
},
"expected": {
"decision": "deny",
"dataReturned": false
},
"observedInExample": {
"status": 200,
"resourceTenant": "B"
},
"evidenceReferences": [
"AUTH-E01",
"AUTH-E02",
"AUTH-E04"
]
}Limits: this paired observation demonstrates the specified read path. It does not by itself establish access to every tenant, write permission, administrative privilege or a count of exposed records. Those are separate questions with separately authorised tests.
Prove the boundary in both directions.
The fixture below defines two tenants and two roles. A reader may read within its own tenant; an editor may read or update there. Every cross-tenant operation is denied. This intentionally narrow model produces 16 policy cases: 6 permitted and 10 denied. It illustrates a regression specification; it is not a production assessment or a complete enterprise access policy.
| Actor tenant / role | Target tenant | Read | Update |
|---|---|---|---|
| A / reader | A | PERMIT | DENY |
| A / reader | B | DENY | DENY |
| A / editor | A | PERMIT | PERMIT |
| A / editor | B | DENY | DENY |
| B / reader | A | DENY | DENY |
| B / reader | B | PERMIT | DENY |
| B / editor | A | DENY | DENY |
| B / editor | B | PERMIT | PERMIT |
Enforce the policy on every path.
Evaluate actor, action, resource relationship and required classification. Apply scoped data access and consistent decisions to direct, batch, export and signed-download flows. Denied operations must not reveal object content or sensitive metadata.
Verify the deployed behaviour.
Repeat controlled negative and positive cases in the agreed environment. Check removed membership, stale authorisation, delegated roles and permission changes. Correlate application traces to the exact tested build and policy version.
A production matrix extends beyond this fixture: document ownership, delegated access, legal-entity segregation, service identities, lifecycle states and concurrent permission changes may all affect the correct decision.
The reasoning behind the controls.
The finding is simple to state; the engineering problem is maintaining the same access rule across every way a document can be selected, cached, transformed or delivered. This technical annex explains the model behind the synthetic test and the questions we would resolve with the application owner.
- Trusted context
Verify the actor and resolve current entity membership from authoritative information.
- Resource and policy
Resolve the protected object, relevant state and the versioned policy used for the action.
- Decision before disclosure
Apply the relationship and action rules before returning protected content or creating an effect.
- Every delivery path
Preserve the boundary in cached reads, writes, exports and later downloads; deny when required authority cannot be established.
Define the security property before choosing a control.
In this example, a tenant represents a separately entitled organisation or legal entity. The protected resource is a particular document version. The subject is the authenticated user or workload, and the action might be read, update, export or share. The central question is whether the current relationship between these objects permits the requested action. A successful login establishes an identity; it does not establish that relationship.
For the narrow fixture, a permit requires an active membership in the document’s tenant and a role allowing the operation. A production model might also consider classification, ownership, delegated access, a transaction workspace and the document’s lifecycle state. Role-based access control is useful for coarse capabilities. Attribute-based or relationship-based policies express restrictions such as an external adviser having access to one engagement, without granting access to every document held by the same office.
PERMIT = verified subject ∧ current membership ∧ entitled resource relationship ∧ permitted action ∧ satisfied contextA missing attribute, unavailable policy dependency or unrecognised operation needs an explicit outcome. For the protected read in this reference design, an indeterminate decision produces no document data. Public resources, exceptional administrative access and emergency procedures would have separate, documented policies; they should not emerge accidentally from a default branch.
Technical basis: OWASP authorisation design guidance ↗
Back to technical topics ↑Build tenant context from verified authority.
A tenant identifier in a URL, JSON field or custom header is a requested context, not proof of entitlement. The service first validates the credential for its intended issuer and audience, checks its validity and resolves the actor through trusted identity data. Where an actor belongs to several entities, switching the active entity still requires a server-side membership decision. A syntactically valid UUID and an authenticated request do not make a resource authorised.
The proposed request context contains the subject identifier, selected tenant, allowed action set and the membership or policy revision used for the decision. A document identifier is resolved with this context rather than through a global lookup followed by an optional check. For a shared service account, record both the workload identity and the initiating actor. Treating the service account’s broad database access as the user’s entitlement would lose the boundary the application is meant to enforce.
This separation also improves investigation. An audit record can explain which actor requested which operation, which trusted attributes informed the decision and which policy revision was active. Access tokens and document contents do not need to be copied into routine decision logs to establish that relationship. Diagnostic fields should be chosen deliberately because the log store becomes another location holding sensitive metadata.
Back to technical topics ↑Combine application decisions with constrained data access.
The application needs an enforcement point before returning a protected representation or applying an effect. In the proposed design, the repository accepts an authorised tenant context and an object identifier together; updates constrain both the target and the permitted fields. Parameterised queries prevent data being interpreted as query syntax. They do not decide whether an otherwise valid query is entitled to return a particular row.
Database row-level security can add another boundary. PostgreSQL, for example, allows policies to govern which existing rows can be selected and which new or changed rows are acceptable. Its documentation also identifies bypass behaviour: superusers and roles with BYPASSRLS bypass row security, and table owners normally bypass it unless configured otherwise. A real review therefore tests through the actual application role, including its ownership, privileges and security-definer functions, rather than assuming a policy’s presence proves enforcement.
Technical basis: PostgreSQL row security policies and bypass conditions ↗
Connection reuse is a separate test condition. If the application supplies tenant context through connection state, it must establish that context for the operation and prevent it surviving into another tenant’s use of the connection. The precise mechanism depends on the driver, pooling mode and transaction model. We would exercise alternating-tenant requests and failure paths under the deployed configuration, including a rolled-back transaction and an interrupted request.
Back to technical topics ↑Keep the boundary when the request leaves the API.
A correct database query can be undermined by a shared cache entry. If a representation varies by tenant, user entitlement or policy revision, the cache design must preserve those distinctions. Authorise before serving protected cached data; a namespaced key does not replace an access decision. Permission changes also need a defined invalidation or freshness contract. Otherwise, a user removed from an engagement may continue to receive a previously authorised representation.
Technical basis: OWASP multi-tenant cache and asynchronous-work isolation ↗
| Path | Boundary that needs an explicit design | Verification question |
|---|---|---|
| Background export | Carry authenticated actor and tenant references; re-evaluate current permission when the job runs and when the output is collected. | What happens if membership is removed after the job is queued? |
| Batch retrieval | Define per-object authorisation and whether failure rejects the batch or returns only permitted items. | Can a mixed batch expose another tenant’s data, count or error details? |
| Download capability | Authorise issuance; constrain resource, operation and validity; define any supported revocation mechanism. | Can a still-valid issued capability outlive the permission that justified it? |
| Derived document | Apply the intended policy to previews, extracted text, search results and cached summaries. | Does the original document remain protected while its preview becomes public? |
These are separate trust transitions. The corrective design should state where authority is checked again and where a time-limited capability is intentionally relied upon. The customer can then judge the remaining exposure window instead of receiving a vague assertion that all links are secure.
Back to technical topics ↑Account for state changes between a check and an effect.
Consider an editor who starts a document update just before membership is revoked. A permission check and a later database write are two observations of state unless the implementation connects them. This is the time-of-check/time-of-use problem. For this reference design, the owner must specify the operation’s decision point: the state against which permission and resource version must both be valid.
Within one database, an appropriate transaction, conditional update or locking strategy can connect those checks. Across a separate identity service and business database, a local transaction cannot make both systems change atomically. Options include a versioned authorisation contract, a final permission check at the executor and a documented revocation window. The required consistency and availability trade-off depends on the operation’s consequence; a confidential export deserves different scrutiny from a harmless display preference.
The retest should schedule permission and resource changes at controlled points in the workflow, then inspect the effect, not just the HTTP response. A denied update must leave the business record unchanged. An accepted operation must be attributable to a specific permitted state. Where immediate revocation cannot be guaranteed, that limitation belongs in the closure record with an owner and an agreed compensating measure.
Back to technical topics ↑Turn a finding into evidence of a durable correction.
The 16-case matrix above is the smallest explanatory model, not a target coverage percentage. A real test set follows the agreed policy: direct and inherited membership, removed and suspended users, delegated advisers, service identities, resource lifecycle changes and alternate delivery paths. Positive cases matter because a fix that denies every request would preserve confidentiality while breaking the service.
For each case, retain fixture identities, prerequisites, expected policy outcome, observed content or effect, request correlation identifier, deployed build and policy revision. Compare what the receiving client obtains and what the data store changes. A 403 response after a partial write is still a failure; a 200 response containing a generic denial is not proof that another tenant’s record was disclosed.
The commissioning team receives a trace from business rule to test to observed result, with exceptions listed explicitly. That makes the work useful to engineering, risk and procurement: it identifies which boundary was demonstrated, which implementation paths were covered and which assumptions would require a new review after the next product change.
Back to technical topics ↑A usable handover for governance and engineering.
- Executive finding: business consequence, exposure assumptions, accountable owner and the decision required.
- Technical evidence: controlled request pairs, fixture provenance, affected operation and reproducible preconditions.
- Corrective design: the policy decision point, data-access boundary and other routes requiring the same protection.
- Closure record: tested version, policy matrix, negative and positive results, remaining exceptions and explicit sign-off criteria.
Technical references
Background guidance for the methods discussed; these organisations do not endorse this illustrative example.