# Array parameter type confusion in auth

Auth fields arriving as arrays: equality becomes IN, validators skip, or reset links fan out

_Area: Web authentication and account takeover. Seen in 3 disclosed reports; 2 confirmed bounties: $480 and $35,000; latest 2026-10-08. Updated 2026-10-24._

## How it works
Auth code assumes a field holds one scalar. When the same field arrives as a JSON array or `param[]`, that assumption breaks in distinct ways. A lookup meant as "equals" becomes "is in this list" because the ORM emits `IN(...)` [E3](https://bugbountylibrary.com/r/h1%3A1559262.md). A shape check meant to reject non-objects passes for arrays, because `typeof [] === 'object'`; the guard that should have caught it omits `Array.isArray` [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md). Separately, a validator loop tests membership with `claim in payload`, which is always false for arrays, so every validator is silently skipped [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md). In each case the code keeps running on a value it never intended to handle, and the check it relied on no longer applies.

## Where it shows up
- Request bodies converted from form-encoded to JSON, or `param[]=` added to a field name, on login, reset, confirmation, or token endpoints.
- `params[:x]` passed straight into `find_by`/`where` without a scalar cast [E3](https://bugbountylibrary.com/r/h1%3A1559262.md).
- Reset handlers that iterate over the submitted email field and send to every entry [E2](https://bugbountylibrary.com/r/h1%3A2293343.md).
- JWT/claim validators guarded by `typeof payload !== 'object'` with no `Array.isArray` check [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md).
- Validator loops using `claim in payload`, always false for arrays [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md).

## How to review
The invariant: every auth-relevant field must be a single scalar of the expected type before it reaches a lookup, comparison, or validator. Check that the handler rejects arrays and objects explicitly (type check plus `Array.isArray`), not just "is object". For ORM lookups, confirm the value is coerced to a string/scalar so equality stays equality and cannot become `IN()`. For token/claim validation, confirm the payload shape is checked the same way the header is, and that a failed shape check aborts rather than skips validation [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md). For reset flows, confirm the handler does not fan out to submitted entries [E2](https://bugbountylibrary.com/r/h1%3A2293343.md).

## Variants seen
- Array payload skips all claim validators, producing forever-tokens [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md).
- Array email fans the reset link out to attacker addresses, enabling takeover [E2](https://bugbountylibrary.com/r/h1%3A2293343.md).
- Array token becomes `IN()`, turning a lookup into a batched oracle that defeats rate limits [E3](https://bugbountylibrary.com/r/h1%3A1559262.md).

## Why fixes fail
E3's author found the same array-to-`IN` pattern already reported on a different controller, showing point fixes that miss sibling endpoints leave the class open.

## Impact and severity
Outcomes ranged from account takeover via reset fan-out [E2](https://bugbountylibrary.com/r/h1%3A2293343.md) to unlimited token guessing that bypassed rate limits [E3](https://bugbountylibrary.com/r/h1%3A1559262.md) and non-expiring JWTs [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md). Severity rises when the confused field feeds authentication directly, when no rate limit survives the batching, and when the flaw is silent (validators skipped without error) so nothing logs a failure.

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-5hjw-83fp-phq9.md
- E2: https://bugbountylibrary.com/r/h1%3A2293343.md
- E3: https://bugbountylibrary.com/r/h1%3A1559262.md
