API3:2023, Broken Object Property Level Authorization, means a user can read or change individual fields on an object that they should not touch, even when they may legitimately access the object itself. It merges two older categories: excessive data exposure on reads and mass assignment on writes.
Why object level checks are not enough
Object level authorization asks one question: may this user see order 1042? Property level authorization asks a second one: which fields of order 1042 may this user see or set?
An API can pass the first check and fail the second. A support agent may be allowed to open a customer record but not see the full payment note. A host may be allowed to approve a booking but not set the total price.
The read side: returning too much
The usual cause is a shortcut. A handler loads a database row and serializes the whole thing, then trusts the front end to hide the sensitive fields. The mobile app never shows them, so nobody notices, but the raw response still carries them.
OWASP's own scenario is a report flow in a dating app that returns the reported user's full name and recent location to the person filing the report. The app UI may show only a confirmation. The response body says more.
The write side: accepting too much
On writes, the framework binds incoming JSON fields onto an internal object. If the client adds a field the developer never meant to expose, it may be accepted. OWASP gives two examples: a host adds a total stay price field to a booking approval and inflates what the guest pays, and a user adds a blocked field set to false to a video update and unblocks content moderators had restricted.
Neither request needed a stolen credential. Both were ordinary calls with one extra field.
What to do about it
OWASP's prevention advice boils down to a few habits:
- Decide per field who may read it, and check that on every response, not only per object.
- Avoid generic serializers such as a blanket to_json call. Pick the fields you return.
- Keep an explicit allow-list of fields a client may change, per endpoint and per role.
- Add schema-based response validation as a second layer, so an unexpected field fails a test or gets dropped.
- Return only what the business need requires.
The allow-list point matters most. A block-list of dangerous fields fails the day someone adds a new sensitive column. For the write side in depth, see the mass assignment allow-list guide.
How to test for it
Read tests: call each endpoint as the lowest privileged role that can reach it and compare the response fields to the documented contract. Write tests: send extra fields such as role, owner, price or status and confirm the stored object does not change.
Add both as automated checks. Reviews miss quiet one-line serializer changes, and tests do not.
Click through it at your own pace, or open it full screen.
Quick check
Is API3 the same as BOLA?
No. BOLA is about whether you may access an object at all. API3 is about which properties of an object you may read or write once you are allowed in. Both can apply to the same request.
Does hiding a field in the UI count as a control?
No. If the field is in the response body, anyone with a proxy can read it. The control has to sit on the server.
If you want to see how your own endpoints respond, Safeguard offers a free scan at gold.safeguard.sh/scan for dependency and SBOM issues, and policies and gates that can enforce checks in pull requests.
Sources
Last reviewed: 19 October 2026.