# Unvalidated proof index, root or flag

Caller-supplied proof, index, root or flag trusted without binding to committed state

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; latest 2026-05-20. Updated 2026-10-25._

## How it works
A verifier accepts a proof, index, root, or flag from the caller and checks only part of what makes it meaningful. The cryptographic path can be valid while the surrounding binding is missing: the index is never bounded, the root is never tied to a trusted value, or a required flag cannot actually be produced. The assumption that breaks is "a valid proof implies the claimed statement"; the proof only proves what the verifier actually binds it to. Only [E1](https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md) demonstrates this binding flaw directly; [E3](https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md) is a reported instance whose root cause is not confirmed.

## Where it shows up
- Merkle/SPV verifiers that walk a path bit-by-bit using only low index bits, with no `_index < 2**proof.length` check [E1](https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md)
- Cross-chain handlers (`retry*`, message-in entrypoints) that take a caller-supplied message or root and execute mint/transfer instructions; reported, root cause unconfirmed [E3](https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md)
- Contracts that require a flag (e.g. `l1Inclusion=true`) for permissionless paths, where the off-chain prover cannot produce it for some chains [E2](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-8.md)

## How to review
Identify every value the caller supplies that the verifier treats as trusted. For each, find the exact check that binds it to stored state:
- Index: enforced `< 2**proof.length` before path navigation [E1](https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md)
- Root: tied to a trusted/committed value, not just used to hash; verify this explicitly rather than assuming [E3](https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md)
- Flag: the off-chain prover's chain dispatch must return the required value on every supported chain, not panic [E2](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-8.md)
The invariant: a proof accepted by the verifier must uniquely determine the claimed leaf and position, and every required flag must be satisfiable on every supported chain.

## Variants seen
- Index aliasing: `index + k*2**h` yields the same path, forging deposits that drain the bridge [E1](https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md)
- Unbound message root (reported, unconfirmed): forged payload executes mint instructions; root cause described only as inadequate validation [E3](https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md)
- Unsatisfiable flag: permissionless path permanently blocked on a chain because the prover panics — a liveness/DoS sub-case, not a proof-binding flaw [E2](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-8.md)

## Impact and severity
Highest confirmed is bridge drain via forged deposits [E1](https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md); critical. [E3](https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md) reports arbitrary token minting (~$180K) but the root cause is not confirmed, so treat severity as reported, not verified. Functional breakage [E2](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-8.md) is lower severity but blocks core design. Severity rises when the forged value directly authorizes value transfer and when no secondary check (stored root, replay guard) exists.

## Evidence
- E1: https://bugbountylibrary.com/r/cantina%3Acitrea_jul2025%3A3.2.1.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-8.md
- E3: https://bugbountylibrary.com/r/dhl%3A20260520-mapprotocol.md
