-
Notifications
You must be signed in to change notification settings - Fork 22
[Bug] Adapter initialize() is unauthenticated, front-runnable #505
Copy link
Copy link
Closed
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaignCampaign: Third CampaignbugSomething isn't workingSomething isn't workingcontractsInvolves writing or testing Rust/Soroban contracts in packages/contractsInvolves writing or testing Rust/Soroban contracts in packages/contractshardComplex implementation spanning multiple packages or involving Soroban contractsComplex implementation spanning multiple packages or involving Soroban contractssecuritySecurity hardening, vulnerability fixes, or audit-related workSecurity hardening, vulnerability fixes, or audit-related worksorobanInvolves Soroban smart contract invocations or Soroban RPC callsInvolves Soroban smart contract invocations or Soroban RPC calls
Description
Metadata
Metadata
Assignees
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaignCampaign: Third CampaignbugSomething isn't workingSomething isn't workingcontractsInvolves writing or testing Rust/Soroban contracts in packages/contractsInvolves writing or testing Rust/Soroban contracts in packages/contractshardComplex implementation spanning multiple packages or involving Soroban contractsComplex implementation spanning multiple packages or involving Soroban contractssecuritySecurity hardening, vulnerability fixes, or audit-related workSecurity hardening, vulnerability fixes, or audit-related worksorobanInvolves Soroban smart contract invocations or Soroban RPC callsInvolves Soroban smart contract invocations or Soroban RPC calls
Description
BlendAdapter::initialize()(packages/contracts/blend-adapter/src/lib.rs:148-161) sets the adapter's vault, pool, and USDC addresses with norequire_auth()call anywhere in the function, only a re-initialization guard (AlreadyInitialized). The same pattern exists inDefindexAdapter::initialize()(packages/contracts/defindex-adapter/src/lib.rs:67-79).Anyone can call
initialize()on a freshly deployed, uninitialized adapter and set themselves as thevaultaddress, becoming the sole party able to invokedeposit/withdrawon it.This is exploitable in practice because deploy and initialize happen as separate transactions.
scripts/deploy-testnet.shdeploys the adapter at line 74 and only initializes it later at lines 84-86, with the mUSDC asset deploy step in between. Anyone watching the ledger in that window could front-run the real initialize call with their own vault address.Steps to Reproduce
BlendAdapter(orDefindexAdapter) contract without initializing it.initialize(), callinitialize()yourself with an address you control asvault.initialize()call now fails withAlreadyInitialized, and the adapter is permanently bound to the attacker's address.Expected Behavior
initialize()should require authorization from the intended deployer/admin, and deployment should minimize any window where an uninitialized adapter sits exposed.Actual Behavior
Any address can call
initialize()on an uninitialized adapter with no authorization check, permanently claiming it. The deploy script also leaves a multi-step window between deploying the adapter and initializing it.Environment
Possible Cause / Fix
Two changes, both in this issue:
require_auth()on the deployer/admin address as a parameter toinitialize()in bothBlendAdapterandDefindexAdapter, matching the patternMeridianVault::initializealready uses. This is the real fix: it closes the vulnerability in the contract itself, for every deployment path, not just the current script.scripts/deploy-testnet.shso each adapter is initialized immediately after its own deploy call, with no other operations (like the mUSDC asset deploy) in between. This doesn't replace the contract fix, but it shrinks the exposure window as cheap defense in depth, including for any deployment that happens before the contract fix ships.Additional Context
Found during an independent audit of the adapter contracts, verified directly against current source (
packages/contracts/blend-adapter/src/lib.rs,packages/contracts/defindex-adapter/src/lib.rs,scripts/deploy-testnet.sh) rather than taken on the audit's word alone. Same gap exists in both adapters, filing as one issue since the fix is the same shape in each.