August 14, 2026
My First Valid Bug: A Broken Object Level Authorization (BOLA) in Customer API
After months of grinding through labs, courses, and public program testing without a confirmed finding, I finally landed my first valid bug…
By Abobakrmohamed
2 min read
After months of grinding through labs, courses, and public program testing without a confirmed finding, I finally landed my first valid bug bounty report a Broken Object Level Authorization (BOLA) vulnerability on a public Vulnerability Disclosure Program (VDP) on HackerOne. Here's the full story: how I found it, how I confirmed it, and what I learned along the way.
Background
Like most of my recent testing, I approached this program with a simple but effective mindset: whenever an API endpoint takes a resource identifier from the client a customerId, a userId, an orderId assume authorization is broken until proven otherwise. That mindset is exactly what led me here.
The Discovery
While mapping out the application's authenticated API surface, I came across a family of endpoints under:
/api/customer/{customerId}/generic-popup/.../dismiss-generic-popup/api/customer/{customerId}/generic-popup/.../dismiss-generic-popupThese endpoints let a logged-in landlord dismiss an in-product popup notification tied to their account. The customerId in the URL path immediately stood out — it's exactly the kind of user-controlled identifier that's worth testing for object-level authorization flaws.
The question was simple: does the backend actually verify that the authenticated session's customerId matches the one in the URL, or does it just trust whatever ID is passed in?
Confirming the Vulnerability
To test this safely and conclusively, I registered two separate accounts that I fully controlled — Account A and Account B. My testing process:
- Authenticated as Account A and captured a legitimate request to the
dismiss-generic-popupendpoint using Account A's owncustomerId. - Replaced Account A's
customerIdin the URL with Account B'scustomerId, while keeping Account A's session/auth token. - Sent the modified request.
The server responded with 200 OK and {"status":"ok"} — meaning Account A had just successfully written to Account B's customer object, despite having no relationship to or authorization over it.
As a control, I also sent the same request with no authentication at all, which correctly returned 403 Permission denied. That confirmed the issue wasn't a broken auth check across the board — it was specifically that authenticated users weren't being validated against the resource they were trying to modify. Classic BOLA (CWE-639), sitting one layer beneath the more general IDOR category.
Impact
For the specific endpoint I tested, the direct impact was narrow: an attacker could force another user's in-product popup notification to be dismissed. No data was disclosed, and nothing beyond a UI notification flag was modified.
But the real finding isn't really about one popup. The root cause is that customerId is never validated against the authenticated session anywhere in this endpoint family. That's an authorization pattern, not a one-off bug — and patterns like this tend to repeat across every handler that shares the same /api/customer/{customerId}/ structure. If the same missing check exists on endpoints that read or write more sensitive customer data, the impact could scale from "cosmetic" to "serious" very quickly. I flagged this explicitly in my report so the security team could audit sibling endpoints, not just patch the one I demonstrated.
Lessons Learned
A few things stuck with me from this first win:
- You don't need a complex exploit chain to find real impact. This was a straightforward parameter swap between two accounts I owned no tooling beyond Burp Suite, no exotic technique. Authorization testing rewards patience and method more than cleverness.
- Low technical severity doesn't mean low-value reporting. Instead of stopping at "this popup can be dismissed by someone else," I called out the systemic risk that the same broken check likely exists elsewhere in the API. That's the difference between a report that gets a quick nod and one that changes how a team audits their whole endpoint family.
- A clean, minimal PoC matters. Two accounts, one swapped ID, one screenshot of the 200 response versus the 403 unauthenticated control — that was enough to make the vulnerability undeniable to the triage team.
Final Thoughts
For a long time, the first valid bug felt further away than it actually was. Countless hours went into labs, courses, and testing programs with nothing to show for it but "Informative" or "Not Applicable." It's easy in those stretches to wonder if the breakthrough is ever coming.
It turns out the gap between "still trying" and "finally landed one" was smaller than it felt. The same fundamentals I'd been practicing all along methodically testing every user-controlled identifier, not overcomplicating the approach were enough. If you're in that in-between stretch right now, closer than you think: keep testing every ID you see, and keep submitting. The first one is closer than it feels.