# SquidRouterModule: missing caller check lets attacker drain Safe via spoofed delegate

SquidRouterModule's express path trusted caller-supplied delegate for Safe permission checks, letting attacker drain victim Safe's WBTC, wTAO, WETH via Permit2 approvals and swaps.

- Payout: Real-world hack
- Severity: high
- Program: SquidRouterModule
- Credited: DeFiHackLabs
- Disclosed: 2026-05-25
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2026-05/SquidRouterModule_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20260525-squidroutermodule
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** SquidRouterModule expressExecuteWithToken on Ethereum
**Root cause:** The public Axelar express path accepts a caller-supplied payload and uses the delegate encoded in that payload for Safe permission checks, without verifying the caller or payload authenticity.
**Steps:**
1. Attacker calls `expressExecuteWithToken(bytes32(0), "", SQUID_ROUTER_SOURCE, payload, "WETH", 0)` on SquidRouterModule.
2. Payload is `abi.encode(SQUID_ROUTER_MODULE, VICTIM_SAFE, PERMISSIONED_DELEGATE, params)` where PERMISSIONED_DELEGATE has wildcard permissions on the victim Safe.
3. Params contain actions: ERC20_APPROVE token to Permit2 max, PERMIT2_APPROVE token to Universal Router max, UNI_V3_SWAP_EXACT_IN token to u token.
4. Repeat for WBTC, wTAO, and WETH (with NATIVE_WRAP for native ETH).
5. Swaps route Safe's tokens through Uniswap V3 pools into u token, which remains in the Safe.
**How found:** Likely identified that the express path uses a caller-supplied delegate for Safe permission checks without verifying the caller, allowing spoofed payloads to impersonate a permissioned delegate.
**Exploitation:** Attacker spoofed express bridge fulfillment payloads naming a permissioned delegate, causing the module to execute arbitrary actions on the victim Safe: approve Permit2, approve Universal Router, and swap all WBTC, wTAO, and WETH (plus native ETH wrapped) into u token. The Safe's valuable assets were drained into pools, and the Safe received u tokens.
**Insight:** When a module uses a caller-supplied delegate for Safe permission checks, test if you can spoof the delegate to bypass authorization and execute arbitrary actions on the Safe.
