A bug bounty report came in on a tournament platform. The researcher had changed an ID in a request. That was the entire exploit. No sophisticated tooling, no exploit chain, no advanced technique. Just an ID swap and a response that came back with data it should never have returned. Tournaments that belonged to other users. Scores that could be changed. Brackets that could be manipulated. Prize pools attached to results that were now fully under the control of whoever sent that request.
That report landed on my desk as a HackerOne ticket. My job was to reproduce it, confirm it was real, and verify it was fixed after the devs patched it. I was not the researcher who found it. I was the QA engineer who had to understand it well enough to confirm it. That distinction matters because it is exactly the position most QA engineers are in when a security finding surfaces. You did not find it. You have to verify it. And to verify it you have to understand what it is.
If you want the full story of how HackerOne tickets ended up on a QA engineer’s desk, that is covered in I Was a Manual Tester Who Handled HackerOne Tickets. This post is the specific layer about what BOLA and IDOR actually are, when QA teams should check for them, and why they keep getting missed.

IDOR and BOLA Are Not the Same Thing (But Almost)
These two terms get used interchangeably in a lot of content and in casual conversation. They are not identical. Understanding the difference tells you where to look and what kind of test to run.
IDOR — The Broader Vulnerability Class
Insecure Direct Object Reference is a vulnerability that occurs anywhere an application exposes a reference to an internal object without verifying whether the requesting user is allowed to access it. The object can be anything. A database record, a file, a user profile, an invoice, a tournament bracket. The reference can appear anywhere. A URL path, a query parameter, a form field, a request body, a header, a cookie.
The common thread is that the application takes a user-supplied identifier, uses it to fetch or modify an internal object, and skips the ownership check. Anyone who can manipulate the identifier can access or modify objects that do not belong to them. The OWASP Insecure Direct Object Reference Prevention Cheat Sheet covers both URL and POST body variations of this vulnerability along with mitigation guidance if you want the full picture before testing.
IDOR has been part of the OWASP web application security conversation since 2007. It is not new. It is not exotic. It is still showing up in production systems constantly because it is easy to introduce during rapid development and easy to miss during testing if nobody is specifically looking for it.
BOLA — IDOR at the API Layer
Broken Object Level Authorization is OWASP’s term for IDOR when it manifests at the API layer specifically. It has held the number one position on the OWASP API Security Top 10 since the list launched in 2019 and retained that position in the 2023 update. The reason it gets its own category in the API context is that APIs expose object identifiers by design. Every REST endpoint that accepts an ID in the path or query string is a potential BOLA surface.
The mechanics are identical to IDOR. An API endpoint accepts an object identifier, fetches the corresponding record, and returns it without checking whether the authenticated user owns that record. The difference is context. BOLA is specifically about API endpoints and object-level authorization. IDOR is the broader class that includes any direct object reference vulnerability across any surface.
Why the Distinction Matters for QA
Every BOLA is an IDOR. Not every IDOR is a BOLA.
An invoice PDF accessible via a predictable URL with no auth check is IDOR. It does not involve an API endpoint in the BOLA sense. An API endpoint at /api/tournaments/1042 that returns tournament data without checking ownership is BOLA, and also IDOR.
For QA engineers the practical implication is this: IDOR can surface anywhere a reference to an object is exposed to the user. BOLA is the version you check at the API layer specifically during API testing. Knowing both terms means you recognize the pattern wherever it appears, not just in one context.
The Sad Path Nobody Tests
This is where most QA teams lose the coverage without realizing it.
Happy Path Thinking Is the Default
The default test case for any user-facing feature is the happy path. User logs in, accesses their own data, performs the intended action, gets the expected result. That test case gets written, executed, and closed. It passes. The feature ships.
Happy path thinking is not wrong. It is necessary. The problem is when it is the only thinking applied to a feature that has more paths through it than the one the developer intended.
The Fork That Gets Skipped
Every feature that involves a user accessing an object has at least two paths. The path where the user owns the object. And the path where the user does not own the object but tries to access it anyway.
The second path is not an edge case. It is a fork in the code that exists whether you test it or not. If the application does not have an ownership check at that fork, the path leads somewhere it should not. The test case that would catch it is the sad path on access control. User A tries to access User B’s object. What does the application do?
Most QA teams never write that test case because nobody framed it as a test case. It gets thought of as an attack scenario, which belongs to security specialists, rather than a path through the application, which belongs to QA.
It’s Not an Attack. It’s a Test Case.
Reframing BOLA and IDOR as sad path test cases rather than security attacks is the mental shift that makes this accessible to QA engineers without a security background.
You are not trying to exploit the application. You are testing a fork in the code that the developer may or may not have handled correctly. That is QA work. The same instinct that makes you test what happens when a required field is empty, or when a form is submitted twice in rapid succession, is the instinct that should make you test what happens when a user tries to access an object they do not own.
The API security testing for QA engineers post covers this broader framing in detail. BOLA and IDOR are the access control layer of the same argument.
When QA Should Actually Check for This
Not every app. Not every sprint. There are specific conditions that tell you whether the check is worth running.
The Conditions That Trigger the Check
The check is relevant when three things are true at the same time. The application is customer-facing. Multiple users exist with their own accounts. Those users own objects that other users should not be able to access.
User profiles, orders, invoices, documents, messages, tournament brackets, appointments, payment records. Any object that belongs to a specific user and contains data or functionality that should be private to that user is a potential BOLA surface. If only a super admin has access to the system, the check is not relevant. If real users own real objects and other real users exist in the same system, the sad path exists and is worth testing.
Where It Shows Up in the Test Cycle
In practice this check happens in one of two ways on a real QA team. It surfaces during an exploratory testing session after feature and integration tests are done, when someone is poking around the application with enough context to ask the right questions. Or it gets flagged proactively when a multi-user feature is being built, because the presence of user-owned objects is itself the trigger.
It does not need to be a formal security test. It does not need to be in the acceptance criteria. It needs to be in the QA engineer’s pattern recognition. If you know what BOLA looks like, you will notice when the conditions for it exist and run the check as a natural extension of your exploratory session.
Teaching Your Team Without Turning Them Into Security Engineers
The goal is recognition, not exploitation. A QA engineer who understands what BOLA is can look at an endpoint that accepts an object ID and ask whether it checks ownership. They do not need to write an exploit. They need to know the question exists.
On my team, the introduction happened the same way everything else did. A ticket came in, I reproduced it, I showed them what I did and why it mattered. The next time a user profile feature shipped, they knew to check. That is the entire training program. Exposure and explanation. Not a security course. Not a certification. Just knowing what to look for when the conditions are right.
The QA engineer skills beyond testing post covers this philosophy in more detail. Security pattern recognition is one layer of the cross-discipline knowledge that separates a QA engineer who closes tickets from one who protects the product.
What the Test Actually Looks Like
The mechanics are simpler than most QA engineers expect.
The Two-Account Test
Create two accounts with the same user role. With Account A, create a resource or retrieve an existing one. Note the object ID from the URL, the response body, or the request parameters. Switch to Account B’s session. Send the same request to the same endpoint with Account A’s object ID. Read the response.
If Account B receives Account A’s data, the endpoint has a BOLA vulnerability. The ownership check is missing or incomplete. That is a finding worth filing regardless of whether security testing was formally in scope.
Repeat the test for write operations. Can Account B modify Account A’s object? Delete it? Perform actions on it? Each HTTP method that the endpoint accepts is a separate test case. Authorization enforcement that works on GET does not automatically extend to PUT, PATCH, or DELETE.
The Input Field Version
The tournament platform findings came through a different path. The fields themselves accepted special characters and payloads that should have been rejected. The HackerOne researchers documented the exact steps. My job was to follow those steps, confirm the endpoint processed the payload, and verify the finding was real before escalation.
This is the input validation version of the same vulnerability class. The endpoint trusts what it receives. When a field does not sanitize input properly, the attack surface expands from ID manipulation to injection. The security testing for QA engineers post covers the injection side of this in more detail.
Tools You Already Have
The two-account test requires Postman and two browser sessions. That is it for the basic check. You do not need Burp Suite to run the fundamental BOLA test. Burp Suite makes it faster and more thorough, particularly for intercepting and replaying requests across sessions, but the core test is accessible with tools any QA engineer already uses. The OWASP Web Security Testing Guide for API BOLA covers the full testing procedure including HTTP method variations and GraphQL endpoints if you want the formal methodology behind what is described here.
If Burp Suite is available, the best QA tools for website testing post covers how to use it for request interception in a QA context without going deep into penetration testing methodology.
Getting the Finding Taken Seriously
Finding the vulnerability is half the job. Getting it prioritized is the other half.
How You Frame It Changes Everything
The same finding lands differently depending on how it is written. A bug report that says “User can access another user’s tournament data by changing the ID in the request” reads as a minor access control issue. A bug report that says “Any authenticated user can read, modify, and delete any tournament in the system including active tournaments with registered participants and prize pools, by changing a single parameter in the request” reads as a critical data integrity failure.
Both are accurate descriptions of the same finding. The second one communicates the actual business risk. Developers and PMs who are not security-aware need the business impact stated explicitly before they can calibrate the severity correctly. The framing is not spin. It is translation.
Team Synergy as a Force Multiplier
On a team where the PM has a technical background and the dev lead understands security implications, a correctly written bug report gets triaged at the right severity immediately. The finding does not need to be sold. It needs to be accurate and clear.
On a team without that context, even a well-written bug report can get downgraded. A junior dev who does not understand the attack surface will assess the likelihood as low and move it to the backlog. A non-technical PM will weigh it against feature velocity and defer it to a later sprint. This is not malicious. It is a knowledge gap producing a prioritization error.
The team dynamic matters. A culture where anyone, junior dev, QA engineer, PM, can raise a concern and have it heard without politics is a culture that ships fewer security gaps. That is the system working correctly regardless of who surfaces the finding.
When It Gets Downgraded and Why
Security findings on small teams without a dedicated security engineer or DevOps person fall into a gap. It is not nobody’s job officially. It is everybody’s job unofficially, which means it gets done when someone thinks of it and skipped when nobody does.
The findings that survive prioritization are the ones framed in terms of user impact and business risk, filed by someone with enough credibility on the team to be taken seriously, at a moment when the team has the capacity to act on them. All three conditions have to align. That is the reality of security coverage on small product teams and it is worth being honest about rather than pretending a well-written bug report is always enough.
What This Has to Do with Happy and Sad Path Testing
BOLA and IDOR are not a separate discipline. They are a specific application of a testing concept every QA engineer already understands.
Access Control Is Just Another Fork
Every piece of code has forks. Conditions that send execution down one path or another depending on input, state, or context. Happy path and sad path testing exists to cover those forks deliberately rather than accidentally.
The access control fork is: does this user own this object? If yes, return the data. If no, return an error. A QA engineer testing the happy path confirms the first branch. A QA engineer testing the sad path confirms the second. BOLA exists when the second branch is missing entirely or implemented incorrectly.
Testing for BOLA is not a security audit. It is a coverage question. Have you tested both forks on this access control decision? If the answer is no, the sad path is uncovered and the gap is real regardless of whether anyone calls it a security test.
The Test Case You Were Already Equipped to Write
You already know how to test a sad path. You send invalid input and check the error response. You submit a form without a required field and verify the validation fires. You try to complete a multi-step flow out of order and confirm the application handles it correctly.
The BOLA sad path is the same instinct applied to a different fork. You try to access an object you do not own and check what the application does. The test case structure is identical. The only thing that was missing was knowing that this particular fork exists and is worth testing.
That is what exposure builds. Not a new skill. A new application of a skill you already have.
You Don’t Need a Security Title to Catch This
The findings on the tournament platform were not caught by a security engineer. They were caught by bug bounty researchers and verified by a QA engineer who had been shown what to look for. The token URL finding from a different project was caught on a free afternoon by a QA lead who recognized a pattern from HackerOne reports years earlier.
Neither of those required a security certification or a penetration testing background. They required exposure to the pattern and the curiosity to apply it when the conditions were right.
BOLA and IDOR keep showing up in production systems not because developers are careless but because the ownership check is easy to forget during rapid iteration and because most QA teams are not checking for it. Closing that gap does not require a security specialist on every team. It requires QA engineers who know what the sad path on access control looks like and make a habit of testing it when the conditions are right.
That is the job. Not just the happy path. Every fork in the code that matters to the user.




