# Access check bound to wrong identity

Does the identity the check compares against actually reach this code path, or is it a fallback?

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; one confirmed bounty: $12,000; latest 2023-10-11. Updated 2026-10-24._

## How it works
An authorization check is only as good as the identity it compares against. The root cause is a mismatch between the identity the check tests and the identity that actually arrives on the real execution path. Either the check compares against an address the legitimate path never uses (so the gate is dead or bypassable), or the identity is resolved by fallback when the original actor disappears, silently reassigning authority to someone else. The broken assumption is "the caller here is the same principal the check was written for."

## Where it shows up
- Modifiers of the form `msg.sender == trustedContract` where the trusted contract is a gateway or router that authenticates by callback/validation, not by being the caller [E3](https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-01.md).
- Identity fields resolved by fallback: triggerer, owner, or role holder reassigned when an account is deleted or removed [E1](https://bugbountylibrary.com/r/h1%3A894569.md).
- Inherited library contracts (timelocks, governors) with local overrides that drop a state or caller check [E2](https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md).
- Checks that run after the guarded action rather than before it [E2](https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md).
- Dangling memberships or roles that survive account deletion [E1](https://bugbountylibrary.com/r/h1%3A894569.md).

## How to review
For every access check, trace the actual call path and confirm the compared identity is the one that arrives. For `msg.sender == X`, grep X for any call into this function; if none exists, the check is wrong and authentication must come from another mechanism (e.g. `validateContractCall` plus source chain/address) [E3](https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-01.md). For fallback identities, ask what happens when the original actor is deleted or removed, and whether authority silently transfers [E1](https://bugbountylibrary.com/r/h1%3A894569.md). For inherited contracts, diff against upstream advisories and confirm local overrides do not weaken the invariant [E2](https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md). The invariant: the principal authorized is exactly the principal that can act, on every path, including deletion and fallback.

## Variants seen
- Dead gate: modifier requires a caller that never calls, blocking or mis-scoping the real entrypoint [E3](https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-01.md).
- Fallback reassignment: deleted actor's role falls back to another account, granting attacker-controlled execution under victim identity [E1](https://bugbountylibrary.com/r/h1%3A894569.md).
- Ordering flaw plus dropped state check: scheduling verified after execution, and a local override removed the Queued requirement, letting anyone execute [E2](https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md).

## Impact and severity
High: cross-tenant CI token theft and private repo access [E1](https://bugbountylibrary.com/r/h1%3A894569.md); arbitrary execution of DAO proposals and admin-role seizure [E2](https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md); broken cross-chain command path [E3](https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-01.md). Severity rises when the fallback identity carries broad privileges or when the check is the only barrier to privileged execution.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A894569.md
- E2: https://bugbountylibrary.com/r/c4%3A2021-08-notional%3AH-02.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-09-centrifuge%3AM-01.md
