# Anti-abuse token skipped on alternate form

Does every form path, including no-JS fallbacks, enforce the same anti-abuse and CSRF token checks?

_Area: Web authentication and account takeover. Seen in 2 disclosed reports; one confirmed bounty: $5,000; latest 2026-06-22. Updated 2026-11-02._

## How it works
A service protects its main form path with an anti-abuse or CSRF token, then ships a second path (no-JS fallback, deep link, public route, alternate token format) that is assumed to inherit the same protection. It does not. The alternate path either accepts a static sentinel instead of a real token, builds requests from unencoded user input, or is registered as public and skips the check entirely. The assumption that breaks: "the token is mandatory everywhere." Enforcement lives on one code path, not in the shared handler.

## Where it shows up
- A no-JS or alternate form that still works with JavaScript disabled, or accepts a sentinel value like `js_disabled` [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md)
- Tokens minted by the JS path being reusable on the fallback, or across unlimited requests [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md)
- Deep-link handlers that concatenate a token into a URL path or a value into a POST body without encoding [E2](https://bugbountylibrary.com/r/h1%3A1741430.md)
- Masked tokens where the mask (one-time pad) ships alongside the masked value [E3](https://bugbountylibrary.com/r/h1%3A732415.md)
- Endpoints in a `publicRoutes` list that perform state-changing writes [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md)
- State-changing GET requests with no CSRF token and no consent step [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md)

## How to review
For each form or endpoint, find the shared handler and confirm the token check happens there, not only in the primary caller. The invariant: every path that reaches the state-changing write must verify a token the attacker cannot supply or reuse. Check that fallback paths reject JS-path tokens and static sentinels [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md); that user-controlled values are encoded for their exact context (path segment vs body) [E2](https://bugbountylibrary.com/r/h1%3A1741430.md); that any masking pad is not transmitted with the masked secret [E3](https://bugbountylibrary.com/r/h1%3A732415.md); and that public routes doing writes require CSRF and explicit consent, with the bound identity coming from the victim, not the token [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md).

## How finders spotted it
- Noticed the recovery form still worked with JS disabled, contradicting the assumption BotGuard was mandatory, then found `bgresponse=js_disabled` [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md)
- Reviewed the patch for a prior fix and saw token and relPath concatenated unencoded into URL and body [E2](https://bugbountylibrary.com/r/h1%3A1741430.md)
- Read the token construction and saw the one-time pad was the first half of the token, making it non-secret [E3](https://bugbountylibrary.com/r/h1%3A732415.md)
- Code review of the publicRoutes registration found a state-changing GET with no CSRF or consent, and tracing session creation showed the token embedded the attacker's own ID [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md)

## Variants seen
- No-JS fallback skipping anti-abuse proof-of-work [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md)
- Deep-link token/path injection reaching arbitrary endpoints [E2](https://bugbountylibrary.com/r/h1%3A1741430.md)
- Reversible masked CSRF token enabling forgery for arbitrary routes [E3](https://bugbountylibrary.com/r/h1%3A732415.md)
- Public GET handoff binding attacker identity to a victim account [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md)

## Impact and severity
E1 enabled brute-forcing any user's phone number, scaled by IPv6 rotation and a display-name leak [E1](https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md). E4 let an attacker link to an admin and inherit full agent tool capabilities [E4](https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md). E2 created an admin user via CSRF [E2](https://bugbountylibrary.com/r/h1%3A1741430.md). E3 bypassed per-form CSRF when chained with XSS [E3](https://bugbountylibrary.com/r/h1%3A732415.md). Impact rises when the skipped check guards a write that binds identity or grants privilege, and when the alternate path is reachable without authentication.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Abrutecat-com-articles-leaking-google-phones.md
- E2: https://bugbountylibrary.com/r/h1%3A1741430.md
- E3: https://bugbountylibrary.com/r/h1%3A732415.md
- E4: https://bugbountylibrary.com/r/ghsa%3AGHSA-v7j5-vc4m-723w.md
