BOPLA: Broken Object Property Authorization in APIs
BOLA asks “can I touch another object?” BOPLA asks “can I read or write fields I should never see on an object I am allowed to touch?”
OWASP API Security Top 10 (2023) calls this Broken Object Property Level Authorization. Hunters often ship it as “sensitive field in JSON” or “I flipped isAdmin.” Naming it BOPLA helps triagers map the fix: authorize per property, not only per object ID.
Two flavors you will hit
Excessive data exposure — GET /api/users/me or /orders/{id} returns ssn, internalNotes, salary, raw tokens, or other users’ emails nested in includes. The IDOR check passed; the serializer did not.
Mass assignment / property injection — PATCH accepts role, balance, verified, price because the framework bound the whole body to the model. You own the object, yet you escalate by editing privileged keys.
Both are BOPLA. One leaks; one mutates.
How I test without drowning in JSON
- Capture a full create/read/update cycle for one resource as a low-privilege user.
- Diff the response schema against the UI. Hidden fields are candidates.
- On updates, add one suspect key at a time:
role,admin,credits,status,ownerId. - Re-fetch and confirm persistence — not just echo.
- For reads, try
fields=, GraphQL selections,?include=, and legacy/_historyendpoints that return fatter objects.
GraphQL makes BOPLA loud: introspection shows fields the mobile app never queries. REST hides them until you ask.
What separates a payout from noise
Programs shrug at debug: true if nothing sensitive follows. They pay when:
- You read another tenant’s PII through an include you should not get
- You set
role=adminor wallet balance on your own account - You change
priceordiscountserver-side on a checkout object you legitimately own
Cite the exact property, before/after, and the role that should be blocked. OWASP’s A03:2023 writeup is enough reference for most programs.
Fix language that helps engineering
- Explicit allowlists for writable properties per role
- Separate response DTOs for public vs internal consumers
- Server-side authorization on sensitive getters, not only route middleware
- Avoid binding request bodies straight onto ORM models
I stopped reporting “extra JSON fields” as fluff. If the property is authorization-relevant, it is BOPLA — and it sits next to BOLA in every serious API review.