# PrivatePool owner can steal all ERC20 and NFT from user via arbitrary execution

Permissionless PrivatePool owners could abuse the onlyOwner execute() arbitrary-call to transferFrom users' approved ERC20/NFTs, draining wallets of non-deposited assets.

- Payout: Contest reward
- Severity: high
- Program: Caviar
- Credited: ladboy233
- Disclosed: 2023-05-18
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-04-caviar-findings/issues/184
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-caviar%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** PrivatePool.execute() arbitrary external call in Caviar private pools
**Root cause:** execute() lets the pool owner make an arbitrary call to any target with any calldata; since users must approve the pool for baseToken/nft to buy/sell, the owner can call transferFrom on those tokens to move user funds.
**Steps:**
1. Victim approves PrivatePool for max on ERC20/NFT (required to buy/sell)
2. Owner calls `privatePool.execute(address(token), abi.encodeWithSelector(ERC20.transferFrom.selector, victim, hacker, amount))`
3. execute() performs `target.call(data)` as the pool, consuming the victim's approval
4. Victim's tokens transferred to attacker
**How found:** Noticed execute() is an unrestricted arbitrary call gated only by onlyOwner, and that pool ownership is permissionless; combined with the fact users must approve the pool directly (as FlashLoan's safeTransferFrom pull requires), enabling approval harvesting.
**Exploitation:** Malicious pool owner (anyone can create a pool permissionlessly) waits for a user to grant approval to the pool, then calls execute() with transferFrom calldata targeting the approved token/NFT contract to pull the user's entire balance to the attacker.
**Insight:** When a contract exposes an owner-gated arbitrary call and ownership is permissionless, treat any user approval to that contract as attacker-reachable; check whether execute-style functions can target the very tokens users approve.
