Prompt Details
Model
Chat - (gpt-5.6)
Token size
2,962
Example input
[Describe the application architecture, services, modules and tenant model]: A B2B SaaS application called AcmeFlow provides project management for multiple customer organizations. Architecture: React web application API Gateway Node.js/TypeScript backend PostgreSQL shared database Redis distributed cache S3-compatible object storage Elasticsearch search cluster RabbitMQ message broker Background worker service Notification service Analytics service Admin/support portal Tenant model: Each customer organization is a tenant Users belong to one or more tenants Projects, tasks, documents and reports belong to a tenant PostgreSQL uses shared tables with a tenant_id column All tenants share the same application infrastructure
[Describe users, roles, permissions, sessions, tokens and access-control model]: Authentication: Users authenticate using JWT access tokens JWT contains: user_id email tenant_id role Roles: OWNER ADMIN MEMBER VIEWER Authorization is primarily implemented in controllers. Example: GET /api/projects/:projectId Controller: const project = await projectRepository.findById(req.params.projectId); if (!project) { return res.status(404).send(); } if (project.ownerUserId !== req.user.id && req.user.role !== "ADMIN") { return res.status(403).send(); } return res.json(project);
[Describe caches, queues, storage, search, workers, logs, analytics and other shared infrastructure]: Redis cache: project:{projectId} Search index: projects Documents: s3://acmeflow-documents/{tenantId}/{documentId} RabbitMQ job: { "projectId": "123", "requestedBy": "user-10" } Worker loads the project using: projectRepository.findById(job.projectId) Analytics events: { "event": "project_viewed", "projectId": "123", "userId": "user-10" }
[Describe admin tools, support access, webhooks, third-party integrations and service accounts]: Support staff can: Search customers Impersonate users View projects Download documents Reset accounts Support portal has a tenant selector. Admin API: GET /internal/tenants/:tenantId/projects Support users authenticate separately. Webhooks are sent to customer-configured URLs.
[Compliance requirements, isolation expectations, deployment model, known concerns and constraints]: Strong logical tenant isolation One tenant must never access another tenant's customer data Cross-tenant access must be explicitly privileged All privileged access must be auditable Production data must not be used for security testing Existing shared PostgreSQL architecture should remain No destructive testing in production
Example output
PHASE 1 — TENANT MODEL RECONSTRUCTION
Findings
Tenant identity originates from the JWT:
JWT
└── tenant_id
Expected flow:
Authenticated User
↓
JWT tenant_id
↓
Request context
↓
Service
↓
Repository
↓
Database
But the repository API allows:
findById(projectId)
without tenant context.
This creates a dangerous architectural gap.
Ownership model
Tenant
├── Users
├── Projects
│ ├── Tasks
│ ├── Comments
│ └── Documents
Assessment
Suspected weakness: tenant identity is not consistently coupled to resource lookup.
Evidence: repository supports tenant-independent resource lookup.
Severity: 🟠 High potential risk.
---
PHASE 2 — AUTHORIZATION BOUNDARY AUDIT
The project endpoint checks:
project.ownerUserId === req.user.id
or:
req.user.role === "ADMIN"
The problem is that ADMIN is apparently interpreted without checking whether the project belongs to the user's tenant.
Therefore:
Tenant A ADMIN
↓
Requests Project B
↓
Repository finds Project B
↓
User role = ADMIN
↓
Potential ALLOW
This is a classic authorization boundary failure.
Expected check
Authorization should conceptually evaluate:
Authenticated user
+
Tenant membership
+
Resource tenant
+
Permission
not simply:
Authenticated user
+
ADMIN role
Finding
FINDING AUTH-001
Cross-tenant authorization may be bypassed by users with tenant-admin privileges.
Classification: Suspected until controlled test confirms it.
Potential impact:
READ
WRITE
DELETE
Enumeration
---
PHASE 3 — TENANT CONTEXT PROPAGATION AUDIT
Expected:
JWT
↓
tenant-alpha
↓
Request Context
↓
Controller
↓
Service
↓
Repository
↓
tenant-aware query
Actual project detail flow:
JWT
↓
tenant-alpha
↓
Controller
↓
projectId
↓
findById(projectId)
↓
PostgreSQL
Tenant context disappears at the repository boundary.
Critical observation
The repository API does not require tenant context.
Unsafe abstraction:
findById(id)
Safer abstraction:
findByIdForTenant(id, tenantId)
or preferably a repository operating from an immutable authorized tenant context.
Result
Tenant context loss detected.
Severity: 🟠 High
---
PHASE 4 — DATABASE ISOLATION AUDIT
The database contains:
projects
-------------
id
tenant_id
name
owner_user_id
The list query is safe:
SELECT *
FROM projects
WHERE tenant_id = $1;
But detail lookup is:
SELECT *
FROM projects
WHERE id = $1;
This means the database itself does not enforce the tenant boundary.
Risk
If an application-layer authorization check fails, PostgreSQL happily returns another tenant's record.
Important distinction
Having:
tenant_id
does not automatically provide isolation.
The security boundary currently depends heavily on application code.
Finding
DB-001 — Tenant-independent resource lookup
Classification:
Confirmed unsafe design pattern.
Not necessarily a confirmed exploitable vulnerability until the end-to-end test succeeds.
Severity:
🟠 High
---
PHASE 5 — DATA ACCESS PATH FORENSICS
Critical resource:
Project
Read
GET /projects/:id
↓
findById(id)
Potentially unsafe.
List
GET /projects
↓
findProjects(tenantId)
↓
WHERE tenant_id = ?
Appears safe.
Update
Assume implementation:
update(projectId, data)
If it executes:
UPDATE projects
SET name = $1
WHERE id = $2;
then cross-tenant modification could occur.
Delete
Same concern:
DELETE FROM projects
WHERE id = $1;
Result
Isolation is inconsistent across access paths.
This is particularly dangerous because:
List endpoint = safe
Detail endpoint = unsafe
Update endpoint = potentially unsafe
Delete endpoint = potentially unsafe
A developer could incorrectly conclude that the application is secure because the normal tenant list is filtered.
---
PHASE 6 — CACHE & SHARED RESOURCE ISOLATION
Redis key:
project:{projectId}
There is no tenant namespace.
Example:
project:123
Potentially shared by:
Tenant A
Tenant B
If IDs are globally unique, collision may not immediately occur.
However, the bigger problem is authorization.
Suppose:
Tenant A requests Project B
and the cache contains:
project:123 → Project B
The cache can return the object before a database tenant check occurs.
Cache risk
Potential:
Cross-tenant read
Cache poisoning
Incorrect invalidation
Authorization bypass through cached objects
Safer strategy
tenant:{tenantId}:project:{projectId}
But this is defense-in-depth, not a replacement for authorization.
CACHE-001
Severity: 🟡 Medium
---
PHASE 7 — QUEUE & BACKGROUND JOB ISOLATION
Job:
{
"projectId": "project-beta-001",
"requestedBy": "user-alpha"
}
There is no:
tenantId
The worker performs:
findById(job.projectId)
Therefore tenant context is not explicitly preserved across the asynchronous boundary.
Attack/control scenario
If a Tenant A user can cause a job to reference Tenant B's project, the worker may process it because it trusts projectId.
Correct model
{
"tenantId": "tenant-alpha",
"projectId": "project-alpha-001",
"requestedBy": "user-alpha"
}
Worker should verify:
job tenant
=
project tenant
before processing.
Finding
QUEUE-001
Missing tenant context in asynchronous jobs.
Severity:
🟠 High potential risk
---
PHASE 8 — FILE, OBJECT & SEARCH ISOLATION
Object Storage
Storage path:
tenantId/documentId
This is good for organization.
But storage path itself is not authorization.
The application must verify:
requester tenant
=
document tenant
before generating a signed URL.
Search
Single shared index:
projects
If search documents do not contain a reliable tenant field and every query is not filtered, cross-tenant search leakage is possible.
Expected:
query
+
tenant_id = authenticated tenant
Finding
Search isolation cannot be confirmed from the supplied design.
Classification: Unverified.
Severity: 🟠 High potential risk because search can leak multiple records through one response.
---
PHASE 9 — API & INTEGRATION ISOLATION
Potentially dangerous endpoint:
GET /internal/tenants/:tenantId/projects
For privileged APIs, the server must not blindly trust:
tenantId
from the URL.
It must establish:
Support identity
+
approved tenant scope
+
requested tenant
+
audit context
Webhooks
Webhook events should carry tenant identity and be associated with the correct integration.
Potential concern:
event generated for Tenant A
↓
wrong integration lookup
↓
Tenant B webhook
No evidence confirms this currently occurs.
Classification:
Unverified.
---
PHASE 10 — ADMIN & SUPPORT ACCESS AUDIT
Support users can impersonate users.
This is inherently a high-privilege boundary.
Required controls:
Who initiated impersonation?
Which tenant?
Which user?
Why?
When?
What resources were accessed?
When did impersonation end?
Risk
If tenant switching is simply:
select tenant → load tenant
without explicit authorization, a support employee could accidentally access an unauthorized tenant.
Required protections
Explicit support scope
Strong authorization
Audit logging
Reason/ticket reference
Session indicator
Time limitation
Clear tenant identity in UI
Prevent accidental tenant switching
ADMIN-001
Severity: 🟠 High potential risk.
---
PHASE 11 — CROSS-TENANT TEST DESIGN
Test CT-001 — Cross-Tenant Project Read
Preconditions
Tenant A
User: Alice
Role: ADMIN
Tenant B
User: Bob
Role: ADMIN
Project B belongs exclusively to Tenant B.
Test Action
Alice authenticates normally as a Tenant A administrator.
The test attempts to request the synthetic Tenant B project through the normal project API.
No production data is used.
Expected Secure Behavior
HTTP 403
or:
HTTP 404
depending on the application's resource-existence disclosure policy.
The response must not contain:
Project B name
Project B metadata
Project B owner
Project B tasks
Project B document references
Failure Indicator
Any of the following:
HTTP 200
Project B returned
Project B metadata returned
Project B appears in cache
Project B appears in search
Severity
🔴 Critical
if an ordinary tenant administrator can read another tenant's customer data.
---
Test CT-002 — Cross-Tenant Update
Precondition:
Project B belongs to Tenant B.
Alice belongs to Tenant A.
Action:
Attempt a controlled update against Project B using a synthetic harmless field.
Expected:
403/404
Project B remains unchanged.
Failure:
200
+
Project B modified
Severity:
🔴 Critical
---
Test CT-003 — Cross-Tenant Delete
Same structure.
Expected:
403/404
Resource remains intact.
Failure:
Project B deleted
Severity:
🔴 Critical
---
Test CT-004 — Cross-Tenant List
Tenant A requests:
GET /projects
Expected:
Only Tenant A projects
Failure:
Any Tenant B project appears
Severity:
🔴 Critical.
---
Test CT-005 — Search Isolation
Tenant A searches for a unique synthetic Tenant B project name.
Expected:
No result
Failure:
Tenant B project appears
Severity:
🟠 High.
---
Test CT-006 — Cache Isolation
Populate a synthetic project in the cache under Tenant B.
Then access the same project identifier through Tenant A.
Expected:
Denied
Failure:
Cache returns Tenant B object
Severity:
🔴 Critical.
---
Test CT-007 — Background Job Isolation
Create a Tenant A job referencing only Tenant A resources.
Verify worker processing retains:
tenant-alpha
Then test a synthetic mismatched pair:
tenant-alpha
project-beta
Expected:
Worker rejects job
Failure:
Worker processes Project B
Severity:
🔴 Critical.
---
PHASE 12 — LEAKAGE & FAILURE-MODE ANALYSIS
Surface Risk Type Status
Project read Cross-tenant object retrieval READ Suspected
Project update Unauthorized modification WRITE Suspected
Project delete Unauthorized deletion DELETE Suspected
List Tenant filtering ENUMERATION Appears protected
Search Missing tenant filter possibility ENUMERATION/READ Unverified
Redis Shared cache namespace READ Suspected
Queue Missing tenant context READ/WRITE Suspected
Storage Authorization dependency READ Unverified
Admin portal Tenant switching READ/CONTROL Unverified
Logs Tenant data exposure INFERENCE Unverified
---
PHASE 13 — RISK SCORING & BLAST RADIUS
Finding AUTH-001
Cross-tenant authorization bypass
Exploitability: High
Privileges: Tenant ADMIN
Data sensitivity: High
Tenant exposure: Potentially broad
Persistence: Medium
Detection difficulty: Medium
Business impact: Severe
Severity: 🔴 Critical if exploitation is confirmed
Potential blast radius:
One compromised/abusive tenant administrator
↓
Potentially arbitrary project IDs
↓
Other tenants' projects
---
Finding DB-001
Tenant-independent repository lookup
Severity:
🟠 High
Blast radius:
Potentially every resource using the vulnerable repository pattern.
---
Finding CACHE-001
Tenant-less cache namespace
Severity:
🟡 Medium
Could become Critical if authorization is performed after cache retrieval or cached objects are directly exposed.
---
Finding QUEUE-001
Missing tenant context in jobs
Severity:
🟠 High
Could become Critical if attacker-controlled resource IDs reach privileged workers.
---
PHASE 14 — REMEDIATION ARCHITECTURE
AUTH-001 Remediation
Unsafe
findById(projectId)
Better
findByIdForTenant(projectId, tenantId)
Query:
SELECT *
FROM projects
WHERE id = $1
AND tenant_id = $2;
But systemic enforcement is preferable to relying on every developer remembering this manually.
Authorization
Use a centralized policy:
authorize(
principal,
action,
resource
)
Example:
authorize(
Alice,
"project:read",
Project B
)
Policy evaluates:
Alice tenant
=
Project B tenant?
If not:
DENY
---
DB Remediation
Consider PostgreSQL Row-Level Security where compatible with the deployment architecture.
Conceptually:
Application tenant context
↓
Database session context
↓
RLS policy
↓
Only tenant-owned rows
This provides defense-in-depth.
---
Cache Remediation
Use:
tenant:{tenantId}:project:{projectId}
And never rely on cache namespacing as the sole authorization mechanism.
---
Queue Remediation
Every tenant-owned job should contain immutable tenant context:
{
"tenantId": "tenant-alpha",
"projectId": "project-alpha-001",
"actorId": "user-alpha"
}
Worker validates resource ownership before processing.
---
Storage Remediation
Use tenant-aware object paths:
tenants/{tenantId}/documents/{documentId}
Before signed URL generation:
authenticate
→ authorize
→ verify document tenant
→ generate URL
---
Search Remediation
Every searchable document should have:
tenant_id
and every tenant query must enforce the tenant filter.
---
PHASE 15 — TENANT ISOLATION HARDENING BLUEPRINT
CURRENT STATE
JWT
↓
Controller
↓
Some tenant checks
↓
Repository
↓
Sometimes tenant-filtered DB query
↓
Shared cache
↓
Shared queue
↓
Shared search
Main weakness:
Tenant context is optional at several boundaries.
---
TARGET STATE
┌─────────────────────┐
│ Authenticated Actor │
└──────────┬──────────┘
↓
┌─────────────────────┐
│ Immutable Tenant │
│ Security Context │
└──────────┬──────────┘
↓
┌─────────────────────┐
│ Centralized │
│ Authorization │
└──────────┬──────────┘
↓
┌────────────────┴────────────────┐
↓ ↓
Tenant-aware API Tenant-aware Service
↓ ↓
└────────────────┬────────────────┘
↓
Tenant-aware Repository
↓
Tenant-scoped Database
↓
┌──────────────┬──────────────┬──────────────┐
↓ ↓ ↓ ↓
Cache Queue Storage Search
↓ ↓ ↓ ↓
Tenant Tenant Tenant Tenant
namespace context namespace filter
Required security properties
1. Tenant context must originate from authenticated identity or an explicitly authorized trusted context.
2. Client-supplied tenant IDs must never override authenticated tenant context.
3. Every tenant-owned resource lookup must establish tenant ownership.
4. Every mutation must enforce tenant ownership.
5. Async jobs must carry tenant context.
6. Cache keys should include tenant namespace.
7. Search must enforce tenant filtering.
8. Storage access must validate ownership before signed URL generation.
9. Administrative cross-tenant access must use a separate privileged authorization path.
10. Automated cross-tenant tests should run in CI.
---
PHASE 16 — FINAL SaaS TENANT ISOLATION AUDIT REPORT
1. 🎯 Executive Security Summary
The synthetic AcmeFlow architecture has a significant tenant-isolation weakness.
The primary architectural problem is that tenant context is not mandatory throughout the data-access layer.
The strongest concern is:
tenant-aware authentication
↓
tenant-unaware repository
This creates opportunities for cross-tenant authorization failures.
Overall readiness: NOT READY
---
2. 🏢 Tenant Model
Tenant model is straightforward:
Tenant
└── Users
└── Tenant-owned resources
However, resource ownership is not consistently enforced at every access layer.
Assessment: 🟠 Needs hardening
---
3. 🔐 Authorization Boundary Assessment
Primary issue:
ADMIN role
+
resource ID
may be sufficient to authorize access without proving:
resource tenant = user's tenant
Assessment: 🔴 Critical potential risk
---
4. 🧭 Tenant Context Flow
Tenant context exists in JWT but is lost at:
Repository
Queue
Potential cache
Potential search
Assessment: 🔴 Unsafe propagation model
---
5. 🗄️ Database Isolation Findings
Shared PostgreSQL tables are acceptable for logical multi-tenancy when consistently enforced.
Current problem:
WHERE id = $1
instead of:
WHERE id = $1
AND tenant_id = $2
Assessment: 🟠 High
---
6. 🔍 Data Access Findings
Different access paths have different isolation guarantees.
List → tenant-filtered
Detail → tenant-unaware
Update → potentially tenant-unaware
Delete → potentially tenant-unaware
Assessment: 🔴 Critical potential risk
---
7. ⚡ Cache & Shared Resource Findings
Redis key:
project:{id}
does not encode tenant identity.
Assessment: 🟡 Medium
Could escalate if cache retrieval bypasses authorization.
---
8. 🔄 Queue & Background Job Findings
Jobs do not contain tenant identity.
Worker relies on:
projectId
rather than:
tenantId + projectId
Assessment: 🟠 High
---
9. 📁 Storage & Search Findings
Storage path includes tenant ID, which is positive.
However:
storage namespace ≠ authorization
Search isolation has insufficient evidence.
Assessment: 🟠 High potential risk
---
10. 🔌 API & Integration Findings
Internal tenant APIs and webhook routing require stronger explicit tenant authorization and context validation.
Assessment: 🟠 High potential risk
---
11. 👑 Admin/Support Access Findings
Impersonation and tenant switching represent high-risk privileged paths.
They require:
Explicit authorization
+
audit trail
+
scope
+
time limitation
+
clear tenant context
Assessment: 🟠 High
---
12. 🧪 Cross-Tenant Security Test Plan
Minimum automated suite:
CT-001 Read
CT-002 Update
CT-003 Delete
CT-004 List
CT-005 Search
CT-006 Cache
CT-007 Queue
CT-008 Storage
CT-009 Export
CT-010 Webhook
CT-011 Admin impersonation
CT-012 Tenant switching
Every test should use:
Tenant A synthetic data
Tenant B synthetic data
and verify:
Tenant A cannot access Tenant B.
---
13. 🚨 Leakage & Failure Modes
Most concerning paths:
Direct API access
↓
Tenant-unaware repository
Async job
↓
Missing tenant context
↓
Tenant-unaware worker
Cache
↓
Tenant-less namespace
Search
↓
Potential missing tenant filter
Potential consequences:
READ
WRITE
DELETE
ENUMERATION
INFERENCE
---
14. 📊 Risk & Blast-Radius Matrix
ID Finding Status Risk
AUTH-001 Admin cross-tenant authorization weakness Suspected 🔴 Critical
DB-001 Tenant-independent repository lookup Confirmed design weakness 🟠 High
DATA-001 Inconsistent resource access paths Suspected 🔴 Critical
CACHE-001 Tenant-less cache keys Confirmed design weakness 🟡 Medium
QUEUE-001 Missing tenant context in jobs Confirmed design weakness 🟠 High
SEARCH-001 Search tenant filtering Unverified 🟠 High
ADMIN-001 Privileged tenant switching Unverified 🟠 High
Highest blast-radius issue
AUTH-001 / DATA-001
Because the same repository pattern may be reused by multiple endpoints, one architectural weakness could affect many resources.
---
🛠️ Remediation Priority
P0 - Immediate
1. Make tenant-aware authorization mandatory.
2. Eliminate tenant-unaware resource access for tenant-owned objects.
3. Audit all findById, update, delete, and raw SQL operations.
4. Add cross-tenant API tests.
5. Verify admin authorization separately.
P1 - High Priority
1. Add tenant context to every asynchronous job.
2. Validate resource tenant inside workers.
3. Enforce tenant-aware search filtering.
4. Harden signed URL generation.
5. Review exports and bulk operations.
P2 - Defense in Depth
1. Tenant-aware Redis namespaces.
2. Database Row-Level Security where appropriate.
3. Centralized authorization policies.
4. Automated repository-level tenancy tests.
5. Cross-tenant security regression suite.
---
🚀 Final Isolation Readiness Verdict
VERDICT: 🔴 NOT READY FOR HIGH-CONFIDENCE MULTI-TENANT ISOLATION
The architecture has the right basic tenant concept, but the tenant boundary is not consistently enforced end-to-end.
The central architectural weakness is:
Tenant identity is mandatory at authentication
but optional at resource access.
The target security principle should be:
NO TENANT CONTEXT
=
NO TENANT-OWNED RESOURCE ACCESS
And more specifically:
Authenticated Principal
↓
Authorized Tenant Context
↓
Authorized Resource
↓
Tenant-Aware Data Access
↓
Tenant-Aware Shared Resources
The most important next validation is CT-001 through CT-007 using two synthetic tenants. If the cross-tenant read or mutation tests succeed, the suspected Critical findings become confirmed Critical vulnerabilities.
Sample test conclusion: The application should not receive an isolation-ready designation until tenant-aware authorization and tenant-aware data access are enforced systematically across synchronous APIs, asynchronous workers, caches, search, storage, and privileged tooling.
By purchasing this prompt, you agree to our terms of service
GPT-5.6
A single broken authorization check can expose one customer's SaaS data to another tenant. 🚨
You Get :-
🔐 Detect broken tenant authorization boundaries
🕵️ Find cross-tenant data leakage paths
🗄️ Audit database & query isolation
⚡ Analyze caches, queues & shared resources
🔌 Review APIs for tenant-boundary flaws
🧪 Build tenant-isolation security tests
🚨 Prioritize critical isolation risks
Find the tenant-isolation weaknesses attackers could exploit before your customers do. 🔒
...more
Added over 1 month ago
