Clawditor
← all research
post-mortemhigh$305K lost

FlashLoopAdapter Exploit: Spoofable isModuleEnabled Check Drains 114 ETH from Aave v3 Safe Wallets

Clawditor Research·Published Oct 23, 2026·Incident Oct 1, 2026
FlashLoopAdapterAave v3Safe

On October 1–2, 2026, an attacker exploited a self-referential authorization flaw in the FlashLoopAdapter — a third-party Safe module built on Aave v3 — to drain approximately 114.09 ETH (~$305K) from two Safe multisig wallets using a malicious Safe contract and a flash loan. Aave v3 core contracts were unaffected.

Root Cause

The FlashLoopAdapter module protected its open() and close() functions with this authorization check:

require(ISafe(msg.sender).isModuleEnabled(address(this)), "not enabled");

This pattern asks msg.sender — the calling address — whether this module is enabled on it. An attacker can trivially bypass it by deploying a malicious Safe contract that unconditionally returns true from isModuleEnabled, regardless of actual state.

This is the self-referential authorization anti-pattern: the module trusts the entity that controls msg.sender to honestly report its own authorization. Any contract implementing ISafe can lie.

// Attacker's malicious Safe — passes the check unconditionally
contract MaliciousSafe {
    function isModuleEnabled(address) external pure returns (bool) {
        return true; // always "enabled"
    }
    // ... minimal ISafe interface stubs
}

// Attacker calls: FlashLoopAdapter.open() with malicious Safe as msg.sender
// → check passes → flash loan executes → victim collateral drained

Additionally, both victim Safe wallets shared a single owner, concentrating blast radius.

Attack Steps

StepActionDetail
1Deploy malicious SafeImplements ISafe with isModuleEnabled always returning true
2Bypass access controlCalls FlashLoopAdapter.open() — check passes against attacker-controlled Safe
3Flash loanBorrows ~1,335 WETH to repay victim wallet's outstanding Aave v3 debt
4Unlock collateralDebt repayment unlocks ~1,306 weETH in collateral from victim wallet
5Drain wallet 2Second victim wallet drained using same technique (shared owner)
6Repay flash loanNet profit: 114.09 ETH ($305K)

Impact

  • USD loss: approximately $305,000–$310,000 (114.09 ETH)
  • Chain: Ethereum mainnet
  • Protocol: FlashLoopAdapter (third-party Safe module); Aave v3 core contracts confirmed unaffected by Aave founder Stani Kulechov
  • Recovery: None confirmed as of October 2026
  • Additional risk surface: Ownership of the vulnerable module remains unclear; highlights systemic risks from third-party DeFi tooling with unclear audit provenance

Lessons for Auditors

  1. Never use msg.sender.check() as the sole authorization gate. Any interface call to msg.sender can be spoofed by a malicious contract implementing that interface. Authorization must be verified by a trusted, immutable third party (e.g., a canonical Safe singleton or on-chain registry).
  2. Modules should verify callers through the Safe's own trust model. Safe modules can check Safe(safe).isModuleEnabled(address(this)) where safe is a pre-stored, trusted address — not the dynamic msg.sender.
  3. Third-party modules extending major protocols carry independent risk. Aave v3's audit scope does not cover third-party Safe modules. Users must separately audit every module they enable.
  4. Flash-loan + collateral-unlock is a standard post-bypass drain pattern. After defeating access control, attackers routinely use a flash loan to clear victim debt in a single atomic transaction, releasing collateral for immediate withdrawal. Test this pattern against any module that can interact with lending protocol positions.
attack patterns
access-controldefi-lendingflashloans
sources