MM-006
MetaMask · validateDelegation Guard Bypass via decodedPermission
MetaMask Delegation Toolkit · HIGH · T1 (1s) · Pairs with MM-005 · S_delegation
HIGH S_delegation READY TO FILE ← SSAF
VECTOR
SHAPE
LEAN4
PoC
Attack Vector
The validateDelegation() guard in MetaMask DelegationManager uses a decodedPermission parameter to check caveat compliance. An attacker can supply a crafted decodedPermission that passes structural validation but encodes permissions beyond the delegation's actual caveat set — bypassing the guard entirely.
Kill Chain
1Attacker holds delegation D with restricted caveats
2Constructs decodedPermission with extra perms not in D
3validateDelegation checks structure, not semantic coverage
4Guard passes — attacker executes with elevated permissions
Root Cause · S_delegation (bypass variant)
Guard validation is structural (checks format) but not semantic (checks that claimed permissions ⊆ granted caveats). The decoder/encoder mismatch creates an escape hatch from the permission boundary.
Relation to MM-005
MM-005 = non-inheritance at delegation creation. MM-006 = bypass at delegation validation. Same root cause (S_delegation), different exploit point. File as paired reports with shared root cause.
Shape · S_delegation (bypass variant)
Guard predicate:
validateDelegation(d, decodedPerm) = structValid(decodedPerm)

Should be:
validateDelegation(d, decodedPerm) = structValid(decodedPerm) ∧ semanticSubset(decodedPerm, d.caveats)

The missing semanticSubset check is the vulnerability. Any structurally valid permission passes the guard regardless of actual caveat scope.
γ₁ Stratum · T1 (1s)
T1 — UI consent / session gate. Exploit occurs at execution time when the malicious decodedPermission is submitted. Single-round attack.
Lean 4 Theorem Backing
Theorem · GuardBypassViaDecodedPermission
-- A guard is sound if it validates semantics, not just structure def soundGuard (validate : Delegation → Permission → Bool) (caveatOf : Delegation → Finset Perm) : Prop := ∀ (d : Delegation) (p : Permission), validate d p = true → p.perms ⊆ caveatOf d -- MetaMask validateDelegation is NOT a sound guard: theorem mm_validate_delegation_unsound (vd : Delegation → Permission → Bool) (h_struct_only : ∀ p, structValid p → vd d p = true) (h_no_semantic : ∃ p, structValid p ∧ ¬(p.perms ⊆ caveatOf d)) : ¬ soundGuard vd caveatOf := by intro h_sound obtain ⟨p, hstruct, hsuper⟩ := h_no_semantic have := h_sound d p (h_struct_only p hstruct) exact hsuper this
PoC (code analysis)
1Locate validateDelegation() in DelegationManager.sol
2Trace decodedPermission parameter validation path
3Construct permission with extra perms beyond delegation caveats
4Confirm guard passes despite semantic overflow
Filing Status
READY — FILE WITH MM-005
Programme: MetaMask (hackerone.com/metamask)
CLO signed ✅ · Priority P2
Shared root cause note: S_delegation family
Expected: $5K–$50K (combined with MM-005)
🦊 HIGH · S_delegation (bypass) · PAIR MM-005 · T1 · $5K–$50K
γ₁ = 14.134725141734693 · V14 · Day 113