Skip to content

Back to the catalog

State divergence enables unauthorized access
blog.trailofbits.comwriteup

State divergence enables unauthorized access

Trail of Bits found and reported an authorization bypass in Provenance Blockchain's marker module (Cosmos SDK) that let any user with zero tokens self-grant ACCESS_ADMIN on non-fixed-supply marker accounts, because the access check compared caller balance against a stale on-chain supply field that never diverged from zero. The bug affected 82 live mainnet markers (tokenized loans, bridged stablecoins, consortium deposits, governance escrow) and allowed two-transaction exploitation to mint arbitrary tokens or drain roughly $500,000 in escrowed nhash; it was mitigated in v1.28.0 (PR #2627) and fully fixed in v1.29.0 (PR #2734) by reading live bank-module supply with an explicit zero-guard.

TL;DR Trail of Bits found a state-divergence bug in Provenance Blockchain's Cosmos SDK marker module that let anyone with zero tokens self-grant admin and drain/mint against 82 live mainnet financial markers.
Document

What it is

A privilege-escalation bug in Provenance Blockchain (Cosmos SDK proof-of-stake chain), reported by Trail of Bits. It affects versions before 1.28.0 and let any user grant themselves admin control over marker accounts without holding any tokens. Found March 2026, reported April 1, 2026. It touched 82 live mainnet markers.

How it works

AddAccess authorizes a caller if any of three conditions holds; condition 3 is "caller controls 100% of circulating supply," implemented by accountControlsAllSupply. That function reads m.GetSupply() — the supply field on the marker struct. For non-fixed markers, the bank module is the source of truth and the struct field is never written back after minting, so it stays at its activation value of 0. The check therefore reduces to comparing the attacker's zero balance against a stale zero: 0 == 0, unconditionally true. Attack is two transactions — MsgAddAccessRequest to grant permissions, then MsgMintRequest (inflate) or MsgWithdrawRequest (drain escrow).

Preconditions / Affected

Non-fixed-supply markers activated with zero supply. All 82 affected markers had stored supply 0 while carrying real circulating/escrowed value. No tokens or prior privileges needed by the attacker.

What to do

Upgrade to v1.29.0 (June 8, 2026), which ships the full fix in PR #2734 — both sides of the comparison now read from the bank module, eliminating the stale field.

Critically, v1.28.0 is not a complete fix. Its mitigation (PR #2627, commit c81fd65, May 1, 2026) only added a zero-supply guard: a marker with stored supply 0 now fails the check. But the comparison still reads the stale struct field, so it still passes whenever that field is non-zero and happens to equal the caller's balance. If you are on v1.28.0, you are on a partial mitigation, not the fix.

Caveats

  • Even the live-supply fix does not fully close the class: a freshly deployed marker with no tokens minted also has live supply 0, so a zero-balance attacker could still match it (the page cuts off mid-sentence here, implying an additional zero-state guard is still required).
  • Impact split by vector: escrow withdrawal was the direct path (~30×10¹⁵ nhash, ≈$500K, largest three markers being Foundation governance/reward/grant funds). Mint inflation across 74 markers (bridged stablecoins, wrapped BTC/USDC, tokenized mortgages, yield tokens) was broader but constrained — for KYC-restricted tokens it was mainly a solvency/integrity threat rather than free inflation.
flowchart TD
    A[MsgAddAccessRequest, zero balance] --> B{accountControlsAllSupply}
    B -->|reads stale struct field = 0| C[0 == 0 true]
    C --> D[attacker gets ACCESS_ADMIN/MINT]
    D --> E[MsgMintRequest: inflate]
    D --> F[MsgWithdrawRequest: drain escrow]
    B -.v1.28.0 zero-guard.-> G[fails if stored supply 0]
    B -.v1.29.0 reads bank module.-> H[no stale field to diverge]

Organisations named here

  • accountControlsAllSupply
  • MsgAddAccessRequest
  • MsgMintRequest
  • MsgWithdrawRequest

Technologies named here

  • Provenance CLI
  • Provenance Blockchain
  • Provenance public REST API
  • Cosmos SDK

Techniques named here

  • State divergence / stale state authorization bypass
  • Access control check bypass via zero-equality shortcut
  • Two-transaction privilege escalation and exploitation