# Stale grants after revocation

Removed or downgraded members, roles, keys, tokens, or indexes still authorizing access

_Area: Web access control and IDOR. Seen in 13 disclosed reports; 6 confirmed bounties, median $500, range $200-$3,000; latest 2022-04-22. Updated 2026-10-23._

## How it works
Authorization is decided from a stored artifact — a foreign key, cached role, subscriber list, link token, API key, or search index document — instead of the subject's current state. Revocation updates the membership record but not the copies derived from it, so the old grant keeps validating. The broken assumption: that removing a member, role, or account clears every place authorization is read from. A related shape: authorization is decided without any current-state check at all, so a token or endpoint carries its own authority.

## Where it shows up
- Foreign keys naming a user as owner/author that survive feature deletion (e.g. `project.mirror_user`) [E1](https://bugbountylibrary.com/r/h1%3A819821.md)
- App-scoped admin API tokens returned in GraphQL "info" responses and not revoked on staff removal [E2](https://bugbountylibrary.com/r/h1%3A700831.md)
- Per-share link tokens that are non-user-specific (not bound to a recipient identity), so removing the recipient does not revoke them and they bypass forced-password policy [E4](https://bugbountylibrary.com/r/h1%3A673724.md)
- Secondary renderers (CDN screenshot/preview URLs) exposing a separate static preview token [E7](https://bugbountylibrary.com/r/h1%3A1489077.md)
- Denormalized subscriber/follower lists on child objects [E3](https://bugbountylibrary.com/r/h1%3A442843.md)
- API keys that keep their prior ACL after a permission downgrade [E5](https://bugbountylibrary.com/r/h1%3A99969.md)
- Static per-account reporting API keys never rotated on offboarding [E6](https://bugbountylibrary.com/r/h1%3A399174.md)
- Cleanup hooks that fire on removal but not on role downgrade [E8](https://bugbountylibrary.com/r/h1%3A880863.md)
- Search index documents carrying visibility that is not re-indexed on a parent-scope change such as a transfer

## How to review
For each authorization decision, name the source of truth and confirm it is updated on revoke. Invariant: after removal or downgrade of a member, role, or account, no stored association, token, cached value, key, or index document may still authorize that subject. Grep for `mirror_user`, `subscribers`, `*_token`, `creator`, `manager` columns and trace each delete/remove/downgrade handler to confirm it clears dependent keys, lists, and tokens. For denormalized lists, check the offboarding path explicitly removes the user from child-object relationships, not just the membership row [E3](https://bugbountylibrary.com/r/h1%3A442843.md). For tokens, check whether validity binds to current user state or only a timer/lifecycle [E2](https://bugbountylibrary.com/r/h1%3A700831.md)[E4](https://bugbountylibrary.com/r/h1%3A673724.md)[E7](https://bugbountylibrary.com/r/h1%3A1489077.md). For role transitions, test downgrade separately from removal [E5](https://bugbountylibrary.com/r/h1%3A99969.md)[E8](https://bugbountylibrary.com/r/h1%3A880863.md). For API keys, confirm re-scoping or rotation on downgrade and offboarding [E5](https://bugbountylibrary.com/r/h1%3A99969.md)[E6](https://bugbountylibrary.com/r/h1%3A399174.md). For search indexes, confirm visibility documents are re-indexed or removed when a parent scope changes (e.g. transfer).

## Variants seen
- Stale foreign key accepted as valid author after feature removal [E1](https://bugbountylibrary.com/r/h1%3A819821.md)
- App-scoped admin token surviving staff removal [E2](https://bugbountylibrary.com/r/h1%3A700831.md)
- Stale subscriber list leaking notifications to ex-members [E3](https://bugbountylibrary.com/r/h1%3A442843.md)
- Non-user-specific per-share link token not revoked on recipient removal, bypassing password policy [E4](https://bugbountylibrary.com/r/h1%3A673724.md)
- Old API key retaining prior ACL after downgrade [E5](https://bugbountylibrary.com/r/h1%3A99969.md)
- Static reporting API key never rotated on offboarding [E6](https://bugbountylibrary.com/r/h1%3A399174.md)
- Static preview token never invalidated on password change or removal [E7](https://bugbountylibrary.com/r/h1%3A1489077.md)
- Redaction hook firing on removal but not downgrade [E8](https://bugbountylibrary.com/r/h1%3A880863.md)

## Why fixes fail
Fixes target one token, endpoint, or trigger and leave sibling paths live: E7 expired only the admin-UI preview URL while a separate CDN screenshot token on the same page stayed valid; E8's redaction fired only on removal, not downgrade. When a fix invalidates one grant, enumerate every other place the same authority is minted or read.

## Impact and severity
Led to persistent backdoor push channels [E1](https://bugbountylibrary.com/r/h1%3A819821.md), full store read/write for removed staff [E2](https://bugbountylibrary.com/r/h1%3A700831.md), data leaks to ex-members [E3](https://bugbountylibrary.com/r/h1%3A442843.md)[E4](https://bugbountylibrary.com/r/h1%3A673724.md)[E6](https://bugbountylibrary.com/r/h1%3A399174.md), exposure of now-private content [E7](https://bugbountylibrary.com/r/h1%3A1489077.md), and unauthorized operations after downgrade [E5](https://bugbountylibrary.com/r/h1%3A99969.md)[E8](https://bugbountylibrary.com/r/h1%3A880863.md). Severity rises when the stale grant is long-lived or bypasses policy (password protection, org policy).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A819821.md
- E2: https://bugbountylibrary.com/r/h1%3A700831.md
- E3: https://bugbountylibrary.com/r/h1%3A442843.md
- E4: https://bugbountylibrary.com/r/h1%3A673724.md
- E5: https://bugbountylibrary.com/r/h1%3A99969.md
- E6: https://bugbountylibrary.com/r/h1%3A399174.md
- E7: https://bugbountylibrary.com/r/h1%3A1489077.md
- E8: https://bugbountylibrary.com/r/h1%3A880863.md
