Broken Access Control Testing: Can a User Open Another Customer's Record?
Learn how to run broken access control testing that proves whether a normal user can open another customer's record, and how to document the evidence.

Broken access control testing answers one question every multi-tenant product owner should be able to answer without flinching: can a signed-in user open another customer's record by changing an identifier, replaying a request or guessing a URL? You do not need a full penetration test to find out. You need two demo accounts, a map of the records each one should reach, and a repeatable check that runs against the real application.
What broken access control testing actually proves
Authorisation versus authentication
Authentication asks who you are. Authorisation asks what this specific identity may do to this specific record. Most breaches in this class happen after a perfectly successful login, which is why "the user is signed in" is never an answer to an access control question.
- Authentication failure: someone logs in without credentials, or as the wrong person.
- Authorisation failure: a legitimate user reaches data or actions outside their role or tenant.
- Object-level authorisation failure: the role check passes but the record check is missing, so any valid session can read any record.
Access control is enforced on the server, per object, on every request. Testing proves that the enforcement holds when the request comes from somewhere the interface never intended: an edited URL, a replayed API call, a stale browser tab. It does not prove the application is secure in general, and it should not be sold internally as if it does.
Why server-side checks fail where the UI hides the button
Hiding a button is a design decision, not a security control. If the server trusts the client to send only legitimate requests, an attacker with a browser console, a proxy or a script does what the UI prevented. Missing authorisation checks usually appear in the endpoints added last, in bulk export routes, and in admin tools that reuse a customer-facing API. Every read, update, delete and export crosses the same trust boundary: the client sends an object identifier, and the server decides whether this session may touch it. Good testing concentrates on the server side, because that is the only side that counts.
What this check is and is not: not a penetration test
A scoped access control check exercises known objects across two accounts and records what happened. A penetration test explores unknown weaknesses, chains exploits, tests infrastructure and produces an opinion on overall risk. This check is narrower, cheaper and far easier to repeat, which is exactly why it belongs in the release cycle.
Why broken access control testing matters more than most bug classes
The OWASP Top 10:2025 context
Broken access control sits at the top of the OWASP Top 10:2025 category list, and it has held that position across editions.[1] That placement reflects how often the weakness is found in real applications, not how hard it is to introduce. The OWASP Web Security Testing Guide covers authorisation testing in detail if your team wants the full methodology.[3] A layout glitch annoys one user; a cross-account read exposes one customer's data to another, and the customer may never know it happened. The reputational and legal asymmetry between the two is enormous.

Regulatory exposure: GDPR, SOC 2 and customer trust
Under GDPR, unauthorised disclosure of personal data is a personal data breach, with notification duties and tight deadlines when the risk is high. SOC 2 auditors ask how you detect unauthorised access and how you evidence it. Neither framework requires a penetration test certificate; both require that you can show what you checked and what you found.
How a single cross-account read becomes a breach notification
An IDOR vulnerability — an insecure direct object reference — turns a normal feature into a data feed. Sequential invoice numbers make it trivial to walk a customer base. A cached response can serve one tenant's record to another after a role change. A soft delete can leave records readable through an endpoint that forgot to filter them. One leaked record is already a disclosure. Whether it becomes a reportable incident depends on what the record contains and on whether you noticed. A tester who can demonstrate the read, the timestamp and the account pair turns a hypothetical into a decision your compliance team can act on.
Preparing for broken access control testing on your app
Create two demo users in separate tenants
Use two accounts that belong to different organisations, ideally with one shared role and one elevated role between them. Give each account a few records with obvious, identifiable names. Avoid production data entirely; synthetic records are safer and easier to recognise in screenshots.
Collect the records each user should and should not reach
List every object type: invoices, projects, users, files, messages, exports, audit logs. For each, note the identifiers user B owns and the ones user A owns. Those two lists become the inputs to the test. Preparation is where most of the value is created: if you cannot say which records user B should be denied, no test can tell you whether the denial happened.
Map every endpoint and object identifier the UI calls
Open the developer tools or an intercepting proxy and record the requests behind each screen. You will find more endpoints than screens, and the ones nobody documented are usually where the checks are missing. Include background calls that fire on page load.
Building a permission matrix your test can read
A permission matrix states, in rows, who is asking, for what, and what should happen. Keep it in version control next to the code so it changes when permissions change.
| Role | Tenant | Record | Expected result |
|---|---|---|---|
| Member | A | Invoice A-1001 | 200, record visible |
| Member | A | Invoice B-2001 | 403 or 404, no data |
| Admin | A | Invoice B-2001 | 403 or 404, no data |
| Member | A | Export of tenant B | 403, no file produced |
| Invited user | B | Tenant A settings | Redirect or 403 |
Returning 404 instead of 403 for foreign records is a defensible choice; it avoids confirming that the record exists. What matters is that no record data appears in the response body.
Running broken access control testing step by step
Run the same sequence every time so that results are comparable release to release. Small variations in method hide real differences in outcome.

Walk the UI as user A, then retarget user B's identifiers
Sign in as user A, capture each request, then substitute user B's identifiers and replay. Test the URL bar as well as the request body, and test identifiers in query strings, headers and JSON payloads.
Test read, update, delete and export separately
These fail independently. A product that blocks cross-tenant reads can still allow a cross-tenant update or delete, and bulk exports frequently bypass the per-record checks entirely. Treat each verb as its own test case. Common failure patterns include sequential IDs, cached responses and soft deletes: sequential or guessable identifiers make an IDOR trivial to exploit, but UUIDs only raise the effort — they do not fix missing object-level authorisation. Cached responses can serve a record to the wrong tenant after a role or tenant change, and soft deletes leave rows in place that later endpoints forget to exclude.
Check role changes, invitations and admin routes
Access control regressions cluster around state transitions. Demote a user and check what their existing session can still reach. Accept an invitation to tenant B and confirm tenant A data is gone from every cached view. Reach admin routes directly as a non-admin.
Watch for regressions after every deploy
A working check today proves nothing about tomorrow's release. New endpoints ship without checks, and refactors drop filters that were previously in place. Schedule the same scoped checks against staging before each deploy and against production afterwards.
Practical takeaway: for every endpoint that accepts an object identifier, the server must answer "does this session own this record?" on the same request that returns the data. If that check lives only in the UI, your access control is a suggestion.
What broken access control testing evidence looks like
Evidence is what separates a finding from an opinion. Engineering needs enough detail to reproduce it in minutes, and compliance needs enough context to understand it without reading code.
Screenshots and request traces for each finding
Record the request, the response status, and the record data that should not have appeared. Note the accounts used, the timestamps, and the exact steps. Redact anything sensitive except the minimum needed to prove the leak. Lead with the effect: "User in tenant A could read tenant B's invoice PDF". Then give the request, the response, and the suggested fix. Reserve status codes and stack traces for the appendix; a CTO or compliance lead should not need them to understand the risk.
Reproducible branches the owner reviews
Where a defect is proven, a fix on a separate branch lets the owner see the change and decide whether to merge. That is how Vidabug works: it films narrated walkthroughs of real software as a new user meets it, tests applications the way real users meet them, and where it can prove a defect, proposes a repair on a separate branch the owner reviews.
A narrated demonstration the compliance team can keep
A short narrated video showing two accounts and the cross-account read is far more persuasive than a written claim. It also doubles as training material and an audit artefact. The same approach helps when mapping broken navigation across a large SaaS product, where the evidence requirement is identical.
Turning broken access control testing into a repeatable habit
Add cross-account checks to every release
Make the permission matrix part of the definition of done for any endpoint that accepts an identifier. Run the scoped checks before deploy and keep the evidence attached to the release.
Pair scoped checks with code review and logging
Checks catch what was exercised; review catches what was written. Server logs that record denied cross-tenant attempts give you the third layer, and they shorten incident investigation when something slips through.
Set a threshold for when a finding blocks a deploy
Agree in advance that any confirmed cross-account read, update, delete or export blocks release. Deciding during a release window, with a deadline looming, tends to produce a different answer. Vidabug fits here as a scoped check rather than a substitute for deeper security work: it can run access control checks against a live site with demo users, or against a repository, record the evidence, and propose reviewable repairs — but it does not certify software as bug-free, and it is not a penetration test or a load test.
Conclusion: broken access control testing as a release habit
Broken access control testing is the cheapest way to answer the question your customers implicitly ask: can another user open my records? Two demo accounts, a written permission matrix and a repeatable replay of identifiers will surface most missing authorisation checks long before an attacker does. Run it every release, keep the evidence, and treat any cross-account read as a release blocker.
[1] OWASP Top 10:2025, top10.owasp.org.
[2] OWASP Top 10, owasp.org.
[3] Web Security Testing Guide | OWASP Foundation, owasp.org.
Questions people ask
What is broken access control and how common is it?
Broken access control means the application lets a user reach data or actions they should not be allowed to. It has ranked at or near the top of the OWASP Top 10 for years, and it is the class most likely to expose one customer's record to another.
How do I test whether a user can open another customer's record?
Log in as two separate demo users in different tenants, note the record identifiers each one can legitimately see, then retry those requests with the other user's session. If the server returns the record instead of a 403 or 404, the check has failed.
What is the difference between IDOR and broken access control?
Insecure direct object reference is one specific pattern: an object identifier in a request is trusted without checking that the caller owns it. Broken access control is the wider failure, including missing role checks, unprotected admin routes and tenant mix-ups.
Can I check access control without a penetration test?
Yes. A scoped check with known demo users and a defined list of records gives you clear evidence of cross-account access without the scope, cost or authorisation of a full penetration test. It proves specific findings; it does not certify the application.
How do I prove broken access control to my engineering team?
Record the request, the session used and the response received, then show the same record from the legitimate owner's view. A short annotated demonstration is usually faster to accept than a written report.
What access control regressions appear after a deploy?
New endpoints added without ownership checks, refactors that bypass a shared authorisation helper, changed caching rules and loosened role definitions are the usual culprits. Repeat the same checks after every release.
Sources
- OWASP Top 10:2025 — top10.owasp.org
- OWASP Top 10 — top10.owasp.org
- Web Security Testing Guide | OWASP Foundation — owasp.org