58743 sc low zeroxswapverifier recipient validation bypass
Submitted on Nov 4th 2025 at 11:20:56 UTC by @teoslaf1 for Audit Comp | Alchemix V3
Report ID: #58743
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/utils/ZeroXSwapVerifier.sol
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Summary
The ZeroXSwapVerifier library fails to validate recipient addresses in swap calldata. Despite accepting an owner parameter intended for validation, the library never checks if the recipient in the calldata matches the expected owner. This allows calldata with arbitrary recipient addresses to pass verification, enabling direct fund theft when the library is integrated according to its intended usage pattern.
Vulnerability Details
The library's main verification function accepts an owner parameter:
function verifySwapCalldata(
bytes calldata calldata_,
address owner, // ← Intended to validate ownership
address targetToken,
uint256 maxSlippageBps
) external view returns (bool verified)However, this parameter is never used to validate recipients. The calldata contains two levels of recipient addresses:
Top-level recipient in
SlippageAndActions.recipientAction-level recipients in individual swap actions
Neither is validated against the owner parameter.
Code Evidence
Location 1: Top-Level Recipient Not Validated (Lines 127-131)
Location 2: Action Recipient Discarded (Lines 239-246)
Impact
The library's stated purpose is to validate untrusted calldata from the 0x API (as confirmed by team: "we do not trust this calldata blindly"). However, it fails to validate the most critical field - where the output tokens go.
The library accepts an owner parameter, suggesting it will validate ownership/recipients, but this parameter is never used for recipient validation.
Recommendation
Add Recipient Validation
Validate Top-Level Recipient
Proof of Concept
Proof of Concept
Add this to /test
Running the PoC
PoC Output
Was this helpful?