# Existence Leak via Error Differences

Missing vs forbidden objects returning different status, body, timing, or side effects, leaking existence

_Area: Web access control and IDOR. Seen in 5 disclosed reports; 5 confirmed bounties, median $2,400, range $150-$15,000; latest 2026-10-01. Updated 2026-10-23._

## How it works
Authorization should look binary to the caller: allowed or denied. The weakness is that the system answers a different question first — does this object exist? — and lets that answer escape. A missing object returns "not found" while a forbidden one returns "unauthorized"; a denial body carries object fields; a mutation's side effects differ for real vs invalid targets. The broken assumption is that a correct status code means nothing leaked. Body, timing, and post-action state still carry the answer.

## Where it shows up
- Object fetched by identifier before the RBAC/ownership check runs [E2](https://bugbountylibrary.com/r/h1%3A1916583.md)
- Denial responses (4xx) embedding object fields such as `context.subject` [E1](https://bugbountylibrary.com/r/h1%3A3862641.md)
- Auxiliary endpoints (CSV exports, downloads, `.json` variants) skipping checks the main page applies [E5](https://bugbountylibrary.com/r/h1%3A2381253.md)[E1](https://bugbountylibrary.com/r/h1%3A3862641.md)
- Mutations accepting arbitrary handles/IDs whose side effects (counters, stats) differ for hidden vs invalid targets [E4](https://bugbountylibrary.com/r/h1%3A410015.md)
- Endpoints echoing full container metadata when adding a linked resource [E3](https://bugbountylibrary.com/r/h1%3A662218.md)

## How to review
For each object endpoint, send two requests identical except for the target ID: one existing-but-forbidden, one nonexistent. Diff status, full body, and response time. The invariant: these must be indistinguishable — same status, same body shape, no object fields, comparable timing. Timing differences are rarely the signal here; status and body are. Check ordering: authorization must be evaluated before or independent of the fetch. Inspect complete denial bodies, not just codes, for nested data. Test export/auxiliary endpoints against private and sandboxed resources. For mutations, compare post-action state (counters, notifications) between valid-hidden and invalid targets, not just the response body [E4](https://bugbountylibrary.com/r/h1%3A410015.md).

## Variants seen
- Fetch-before-authz producing not-found vs unauthorized oracle [E2](https://bugbountylibrary.com/r/h1%3A1916583.md)
- Data echoed inside a 422 denial body [E1](https://bugbountylibrary.com/r/h1%3A3862641.md)
- Post-mutation counter as existence oracle [E4](https://bugbountylibrary.com/r/h1%3A410015.md)
- Export endpoint 404 vs success distinguishing private from sandboxed [E5](https://bugbountylibrary.com/r/h1%3A2381253.md)
- Collection-add echoing protected room name [E3](https://bugbountylibrary.com/r/h1%3A662218.md)

## Impact and severity
Led to disclosure of private report details [E1](https://bugbountylibrary.com/r/h1%3A3862641.md), private program existence [E4](https://bugbountylibrary.com/r/h1%3A410015.md)[E5](https://bugbountylibrary.com/r/h1%3A2381253.md), and protected room names [E3](https://bugbountylibrary.com/r/h1%3A662218.md). Severity rises when the oracle is unauthenticated [E5](https://bugbountylibrary.com/r/h1%3A2381253.md) or combines with sequential IDs to become full enumeration [E2](https://bugbountylibrary.com/r/h1%3A1916583.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A3862641.md
- E2: https://bugbountylibrary.com/r/h1%3A1916583.md
- E3: https://bugbountylibrary.com/r/h1%3A662218.md
- E4: https://bugbountylibrary.com/r/h1%3A410015.md
- E5: https://bugbountylibrary.com/r/h1%3A2381253.md
