# Object ID without ownership check

Every client-supplied id must be bound to the caller's identity, role, or tenant before use.

_Area: Web access control and IDOR. Seen in 85 disclosed reports; 30 confirmed bounties, median $2,950, range $100-$15,600; latest 2026-10-30. Updated 2026-10-30._

## How it works
A handler takes an object identifier from the client and looks the object up by that id alone. The code assumes that if the caller can name the object, the caller may touch it. Authentication (who you are) is checked; object-level authorization (whether this object is yours, or within your role/tenant) is not. The lookup succeeds and the caller reads or changes data belonging to another user, role, or tenant. The same gap appears when a check runs on one identifier (the transport URL, the connection) while a second client-supplied identifier in the same request is forwarded downstream unchecked [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md)[E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-4hmc-cfm3-w43c.md).

## Where it shows up
- Fetch/mutate functions taking an id, uuid, tenant id, or global id with no ownership predicate in the query [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-26rh-24rg-j3vv.md).
- Nested-resource routes where a path-prefix auth dependency validates only the outer workspace id; the dependency signature lacks the inner id and structurally cannot scope it [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md).
- Bulk endpoints where the action never verifies the caller's access to each submitted id, and a downstream component returns full details assuming it did [E1](https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md).
- A second object id carried in the request body or resource URI (not the transport URL) that is never re-authorized against the caller [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md)[E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-4hmc-cfm3-w43c.md).
- A secondary client-supplied field (destination/foreign id, e.g. `environmentId`) that must be scoped to the caller's org or project [E8](https://bugbountylibrary.com/r/ghsa%3AGHSA-qxpp-qjg8-x4jv.md).
- A custom finder used by one action instead of the shared authorize helper its siblings use [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md).
- Permission middleware that validates role/permission ids per namespace but not resource ownership [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-26rh-24rg-j3vv.md).
- A check that exists but validates the wrong scope: project visibility instead of account membership, so a foreign id passes [E6](https://bugbountylibrary.com/r/h1%3A3979217.md).
- Sequential or reversible ids (Sqids, incremental, global counters) that make foreign objects easy to name [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md)[E6](https://bugbountylibrary.com/r/h1%3A3979217.md).

## How to review
For every endpoint accepting an object identifier, trace each id to the data layer and confirm the query or resolver binds the object to the authenticated caller. The invariant: an object is returned or mutated only if a check ties it to the caller's identity, role, or tenant.
- Pick the binding matching the object type: owner-column check for user-owned objects, tenant/scope check for shared objects.
- Nested routes: confirm the service-layer lookup filters by the resource's own workspace/tenant column, not just the URL prefix [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md).
- Bulk: confirm the check runs per id, and that any downstream consumer does not assume it happened [E1](https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md).
- Second identifiers: when a connection or URL is authorized on one id, confirm every other id in the body or resource URI is independently bound to the caller [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md)[E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-4hmc-cfm3-w43c.md).
- Form actions: confirm the submitted value is re-validated server-side, not just restricted in the loader [E8](https://bugbountylibrary.com/r/ghsa%3AGHSA-qxpp-qjg8-x4jv.md).
- Custom finders: diff against the shared authorize helper used by sibling actions [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md).
- Wrong-scope checks: confirm the check tests the binding the object actually needs (membership, not visibility) [E6](https://bugbountylibrary.com/r/h1%3A3979217.md).
- Treat any 2xx or normal-looking payload for an object the caller does not own as a failure; silent success is the common shape [E1](https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md).

## Variants seen
- Bulk REMOVE over id arrays with no per-id check; downstream returns full details [E1](https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md).
- Body-supplied task_id authorized only via URL bucket [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md).
- Body-supplied row ids filtered by id only, no namespace check [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-26rh-24rg-j3vv.md).
- Nested-resource routes authorized only by URL workspace prefix; inner ids fetched by primary key, enabling cross-tenant writes and self-promotion to admin [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md).
- Two independent ids: rights gate on container UUID, action on a child UUID never checked against that container [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md).
- Write handler checking project visibility while the read handler checked membership [E6](https://bugbountylibrary.com/r/h1%3A3979217.md).
- Connection-scoped auth on one id, resource URI id forwarded unchecked [E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-4hmc-cfm3-w43c.md).
- Form action trusting a foreign `environmentId` with no membership filter [E8](https://bugbountylibrary.com/r/ghsa%3AGHSA-qxpp-qjg8-x4jv.md).

## Why fixes fail
Fixing one endpoint leaves sibling endpoints (key routes, custom finders) unprotected [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md); the check must be repeated per path or centralized. A path-prefix dependency whose signature lacks the inner id cannot enforce scoping no matter how it is called [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md). A check that validates the wrong scope still passes foreign ids [E6](https://bugbountylibrary.com/r/h1%3A3979217.md).

## Impact and severity
Ranged from private data disclosure to cross-tenant account compromise [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md), cross-tenant writes [E8](https://bugbountylibrary.com/r/ghsa%3AGHSA-qxpp-qjg8-x4jv.md), full internal bug detail exposure [E1](https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md), and privilege escalation to admin [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md). Writes and deletes are worse than reads: destructive mutations corrupt or remove another user's content, while reads leak PII. Severity rises with object sensitivity, breadth of reachable ids, and whether the object is read versus mutated.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Amedium-freecodecamp-org-messing-with-the-google-buganizer-system-for-15-600-in-bounties-58f86cc9f9a5.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-5pg6-m483-7vrg.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-26rh-24rg-j3vv.md
- E4: https://bugbountylibrary.com/r/ghsa%3AGHSA-h8q5-cp56-rr65.md
- E5: https://bugbountylibrary.com/r/ghsa%3AGHSA-x628-457g-2pw9.md
- E6: https://bugbountylibrary.com/r/h1%3A3979217.md
- E7: https://bugbountylibrary.com/r/ghsa%3AGHSA-4hmc-cfm3-w43c.md
- E8: https://bugbountylibrary.com/r/ghsa%3AGHSA-qxpp-qjg8-x4jv.md
