HIGH - Enables unauthorized access via unverified merkle proofs
Detects functions that accept merkle leaf + path but never verify the computed root matches the stored root, or verify after already trusting the leaf value.
// ❌ BAD: Computes root but never checks it
pub fn claim_airdrop(env: Env, amount: u64, proof_path: Vec<BytesN<32>>) {
let leaf = hash_leaf(&env, amount);
let computed_root = compute_merkle_root(&env, leaf, proof_path);
// ❌ Never compares: computed_root == stored_root
// Trust the leaf immediately!
transfer(&env, &env.invoker(), amount);
}Attack: Attacker provides any amount + fake merkle path, gets funds.
// ✅ GOOD: Verify root before trust
pub fn claim_airdrop(env: Env, amount: u64, proof_path: Vec<BytesN<32>>) {
let leaf = hash_leaf(&env, amount);
let computed_root = compute_merkle_root(&env, leaf, proof_path);
let stored_root: BytesN<32> = env.storage().get(&MERKLE_ROOT_KEY).unwrap();
if computed_root != stored_root {
panic!("Invalid merkle proof");
}
// Now safe - proof verified
transfer(&env, &env.invoker(), amount);
}- Authorization bypass: Claim without valid proof
- Fund theft: Access any amount in merkle tree
- Airdrop manipulation: Claim multiple times or wrong amounts
- Find merkle root computation calls
- Check if result compared to stored root
- Verify comparison happens BEFORE leaf trusted
- Flag if missing or misordered
- #1192, #1194: ZK infrastructure
- #1221: Merkle test fixture
See contracts/fixtures/finding-codes/z014_missing_merkle_inclusion_check.rs