# Identifier coercion collision in access control

IDs parsed, coerced or truncated so distinct objects collide and one user reaches another's data

_Area: Web access control and IDOR. Seen in 2 disclosed reports; one confirmed bounty: $3,134; latest 2026-02-03. Updated 2026-11-07._

## How it works
An access check binds a request to an object by an identifier, but the identifier is not compared in its original form. It is decoded, padded, coerced or truncated first, so two distinct objects map to the same key. The authorization decision is then made on the collapsed value, and the wrong object is served. The broken assumption is that "the ID I received identifies exactly one object"; when parsing is lossy or ambiguous, that stops being true.

## Where it shows up
- UUID primary keys attached to a relation whose foreign key column is an integer (Rails ActiveStorage `record_id` as bigint) [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md)
- Any `.to_i`, `int()`, cast or truncation applied to an ID before lookup or comparison [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md)
- Encoded blobs (base64) carrying trusted fields such as a recipient email, with non-standard padding [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md)
- RPC parameters where the object ID doubles as the authorization key [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md)
- Role checks (creator/manager) evaluated instead of current membership [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md)

## How to review
Find every place an identifier crosses a type or encoding boundary before an access decision. The invariant: the value used for the authorization lookup must be byte-for-byte the value stored on the object, with no lossy conversion. Check the schema column type against the model's key type; a UUID stored in a bigint column silently truncates [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md). For encoded parameters, decode fully and confirm the server re-validates the embedded identity against the caller's intent rather than trusting it [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md). For RPCs, confirm the check is current membership, not a historical role [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md).

## How finders spotted it
- A flaky spec failed intermittently; chasing the randomness exposed UUIDs becoming `0` via `.to_i`, then the attachments schema showed `record_id` is bigint [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md)
- DevTools network review: a partner-sharing URL had a base64-looking `request` param ending in `.` instead of `=`; decoding it revealed an embedded email that could be swapped [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md)
- Observed the "View Members" action issuing a batchexecute RPC keyed by space ID, then replayed it with a victim space ID after removal [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md)

## Variants seen
- Type coercion: UUID truncated to numeric prefix in a bigint column [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md)
- Encoding ambiguity: base64 with `.` padding, trusted embedded field [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md)
- Stale authorization: role-based check surviving membership removal [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md)

## Impact and severity
Cross-user data disclosure: private export ZIPs [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md), victim photos [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md), member names and emails [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md). Severity rises with the sensitivity of the object and the ease of guessing a colliding or swappable ID; silent sharing [E1](https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md) and post-removal access [E3](https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md) are especially damaging because the victim sees no signal.

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **decidim-core (rubygems)** >= 0.30.0, < 0.30.4, fixed in 0.30.4: Decidim's private data exports can lead to data leaks (CVE-2025-65017). Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md. Fix: https://github.com/decidim/decidim/pull/13571

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aavatao-com-blog-how-i-could-have-stolen-your-photos-from-google-my-first-3-bug-bounty-writeups.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-3cx6-j9j4-54mp.md
- E3: https://bugbountylibrary.com/r/blog%3Aweb-archive-org-web-20221201043429-https-hopesamples-blogspot-com-2022-11-the-space-creators-can-still-see-html.md
