# Adversary can steal user's NFT's if they have set Magnetar as isApprovedForAll == true

Magnetar router lets any caller invoke ERC721.approve on whitelisted tokens; if a user set Magnetar as approvedForAll, an attacker can approve themselves and steal the NFT.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: deadrxsezzz
- Disclosed: 2024-05-23
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2024-02-tapioca-findings/issues/44
- Library page: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AH-12
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Magnetar router contract / ERC721 approve operation
**Root cause:** _processPermitOperation only checks that the first param (owner) equals msg.sender, but for ERC721.approve the first param is the `to` spender, not the owner; the actual owner check is delegated to the NFT contract, which trusts Magnetar as approvedForAll.
**Steps:**
1. User A sets Magnetar as isApprovedForAll on oTAP/tOLP NFT.
2. Attacker B calls Magnetar with actionCalldata = `IERC721.approve.selector ++ abi.encode(B, tokenId)`.
3. _processPermitOperation decodes first 32 bytes as address = B and _checkSender(B) passes since msg.sender == B.
4. Magnetar calls NFT.approve(B, tokenId); OZ ERC721 sees msg.sender (Magnetar) is approvedForAll for owner A, so approval succeeds.
5. B now owns approval for tokenId and transfers the NFT to themselves.
**How found:** Code review of _processPermitOperation's owner-param check; noticed the comment 'owner address should always be first param' is false for ERC721.approve where `to` is first, and that OZ approve trusts approvedForAll callers.
**Exploitation:** Attacker needs a victim who granted Magnetar approvedForAll (expected since Magnetar is a router). Attacker crafts a permit-operation call with ERC721.approve selector targeting the victim's tokenId, setting themselves as spender, then calls transferFrom to extract the NFT.
**Insight:** When a router validates 'owner is first arg' across heterogeneous selectors, check each selector's actual ABI: ERC721.approve(to, tokenId) has spender first, so a generic first-arg==msg.sender check becomes an authorization bypass for any approvedForAll router.
