# Incorrect implementation of access control in MIMOProxy:execute

MIMOProxy.execute read the permission selector via calldataload(data.offset), so trailing calldata bytes let an envoy bypass the selector check and invoke arbitrary fallback code.

- Payout: Contest reward
- Severity: high
- Program: Mimo DeFi
- Disclosed: 2022-10-17
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2022-08-mimo-findings/issues/159
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-mimo%3AH-04
- Tags: domain:web3 impact:privesc kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** MIMOProxy smart contract execute() access control
**Root cause:** The permission check extracted the function selector with `calldataload(data.offset)` instead of reading the first 4 bytes of the `data` parameter; when `data.length == 0`, this reads trailing attacker-supplied calldata beyond the ABI-encoded arguments.
**Steps:**
1. Identify envoy permission granted for a specific selector on a target.
2. Craft calldata: `execute(target, "")` ABI-encoded, then append the permitted 4-byte selector as extra trailing bytes.
3. Solidity accepts the extra calldata; `data.offset` points past the zero-length data word to the appended selector.
4. `calldataload(data.offset)` returns the permitted selector, passing `_permissions` check.
5. Delegatecall proceeds with empty `data`, hitting the target's fallback function.
**How found:** Code review of the assembly selector extraction; noticed Solidity does not reject redundant trailing calldata, so `calldataload(data.offset)` on empty `data` reads bytes past the ABI arguments.
**Exploitation:** An account holding permission for one function selector calls execute with empty data plus appended selector bytes, bypassing the permission map and triggering the target contract's fallback via delegatecall.
**Insight:** When a contract extracts a selector via inline assembly `calldataload(data.offset)`, check whether `data.length` is validated — Solidity permits trailing calldata, so empty bytes let the read slide into attacker-controlled bytes appended after the ABI-encoded args.
