Multi-tenant isolation: the SaaS pentest gap nobody scopes for
Every B2B SaaS pentest scope says 'web app + API'. Almost none of them say 'cross-tenant data access via IDOR, RLS bypass, JWT scope leaks, shared S3 paths, leaky webhook payloads'. That's the gap.
Built on tools you trust
← swipe · 12 tools →
Every B2B SaaS pentest scope says "web app + API." Almost none of them say "and prove the tenancy model holds under attack." That second sentence is the one that catches incidents in the wild.
The audit playbook for SaaS is well-defined; the same five multi-tenant gaps show up over and over, scoped out of the original pentest by accident.
1. Cross-tenant IDOR
The scenario: tenant A creates resource /api/projects/12345. Tenant B can also reach that URL (no scope check beyond authentication). The pentest scope said "test authentication"; auth was fine — /me returned 401 unauth'd, 200 auth'd. The cross-tenant authorization check was missing because nobody asked for it.
How we test: provision two tenant accounts, make tenant A do a thing, log the resulting IDs, log into tenant B, attempt every URL that references those IDs. Repeat for every resource type.
2. Broken row-level security predicates
The scenario: you use Postgres RLS with a tenant_id = current_user_tenant() predicate. Looks watertight. But one query was written before RLS was turned on and uses SECURITY DEFINER to bypass it for "performance reasons." Now any tenant can call that endpoint and read all rows.
How we test: enumerate every query in the codebase that runs against multi-tenant tables, check whether RLS predicates apply, look specifically for SECURITY DEFINER or bypassrls flags. Then attempt cross-tenant reads via every endpoint that uses those queries.
3. JWT scope leaks
The scenario: you mint a JWT with tenant_id claim. Looks safe. But one of your service-to-service tokens is signed with a wider scope (maintenance task, support tooling) and got exposed via a forgotten Mockoon test setup left in the repo. Or the access-token rotation endpoint accepts an old token's scope.
How we test: read every JWT-signing path, validate scope-claim narrowing on every refresh, look for service tokens checked into .env.example or test fixtures, attempt the wider-scope tokens against production endpoints.
4. Shared S3 / blob storage paths
The scenario: your file uploads land in s3://your-bucket/uploads/<uuid> without a tenant prefix. The presigned URL pattern is predictable. Tenant A uploads a file, tenant B's frontend (which knows the URL shape) generates URLs that probe other tenants' files.
How we test: inspect S3 bucket policies, generate signed URLs for known-shape paths, attempt cross-tenant downloads. Also check whether the bucket allows directory-listing if the prefix is partially known.
5. Leaky webhook payloads
The scenario: you send webhooks to tenant-configured URLs containing event data. Webhook payload accidentally includes data from other tenants (joined in a query that didn't filter by tenant_id). Tenant A configures a webhook URL they control; receives events from tenant B's activity.
How we test: enumerate every outbound webhook, log the full payload, verify no fields contain data outside the receiving tenant's scope. Particularly worth checking: aggregations, "user activity" feeds, search index updates.
Why this isn't standard pentest scope
A standard external pentest is built around the OWASP Top 10. None of those five gaps is in the OWASP Top 10 directly — they're all specializations of "Broken Access Control" (#1) but the test plan for each is different and SaaS-specific.
So pentests written by people who don't live in the SaaS world skip them. The auditor signs off on the SOC 2 because the pentest report came back clean. The cross-tenant data leak ships, gets discovered six months later by a security researcher, and now you have a breach notification to write.
What we do about it
Our cybersecurity-for-saas SKU builds the test plan around exactly these five gaps. We provision the two tenant accounts ourselves before the engagement starts. We diff your codebase for SECURITY DEFINER usage and JWT minting paths. We instrument and inspect every webhook payload during the test window.
Findings come with reproduction steps, an architectural recommendation for the fix, and (in the SKU) the actual remediation pull request.
If your last pentest report didn't have a section called "tenant isolation" — that's the section that should have been there, and it wasn't.
The Hayaiti team
Hayaiti
Hayaiti is a productized engineering studio. We ship web, software, iOS, and cybersecurity work on fixed prices and calendar-day timelines. The team takes turns on the shipping log.
More from the shipping log
PCI SAQ A vs SAQ D: a 10x audit cost decision
The same e-commerce business can fall into two different PCI scopes depending on a single architectural choice. The cost difference is roughly 10x. Most teams don't realize it until the QSA quotes them.
Subdomain takeover: still everywhere in 2026
We checked the top 10K domains for dangling DNS records pointing to deprovisioned cloud resources. The numbers are bad.
Three OAuth state-bypass patterns we keep finding in the wild
Three OAuth state-handling bugs we reported on bug-bounty programs last quarter. All three were exploitable. Here's the pattern, the fix, and why CSRF tokens alone aren't enough.
Want help shipping this?
We turn posts like this into production code. Fixed price. Calendar-day timelines. Source code in your repo on day one.