KINWILDER

Blockchain security · Deep dive

Nomad: when “never seen” became “already trusted”

The dangerous value was not an exotic opcode. It was the default value returned when a proof was missing.

Kinwilder research desk · · AI-assisted analysis

Established findings: default state met trusted state

The August 2022 Nomad bridge incident exploited a gap between message proof state and root acceptance. Coinbase's technical analysis explains how an unproven message could resolve to a zero root that configuration treated as acceptable. It reports more than $186 million in ERC-20 tokens taken during its stated observation window.

Mandiant's investigation examines the mechanism and the many participants who subsequently interacted with it. Its analysis is a reminder that one visible incident need not correspond to one operator. Nomad's public incident-data repository provides additional first-party research material. The commonly cited approximately $190 million incident estimate and a particular researcher's measured window are different quantities.

Kinwilder analysis: the bug lives between two predicates

Imagine one function returning the root associated with a message and another deciding whether that root is trusted. Each can appear reasonable in isolation. The composition fails if the first returns a sentinel for absence and the second accepts that sentinel as authority.

The critical invariant is stronger than “the root is accepted.” It is “this message acquired an authenticated proof, and the root bound to that proof is accepted under the intended state.” A default lookup result cannot establish the first clause. Tests that exercise only ordinary proven messages may never notice the distinction.

This pattern appears in many systems: an unset account identifier that maps to a privileged default, a missing policy version that selects an old permissive policy, or an empty cache entry interpreted as a successful authorization. The shared mistake is allowing a representation of absence to cross a trust boundary as evidence of presence.

A better test than another happy-path withdrawal

Start with a message identifier that has never been proven. Query the exact deployed or migrated state in an authorized local test environment. The assertion should be unambiguous: acceptance must fail, regardless of whether a default root happens to appear in another mapping.

Then test initialization and upgrade sequences. Security invariants must hold immediately after each transition, not only after the application has completed its preferred setup path. Include the zero value, an unset entry, an explicitly rejected entry and a previously valid entry. Distinguish these states in the model even if the implementation compresses them into the same storage representation.

Property-based testing can express the boundary directly: no execution path may accept an unproven message. A second property can require that accepted messages bind to the correct origin, destination, payload and unique processing state. These are suggested defensive properties, not a claim that a particular patch has been verified here.

Operational defenses belong beside contract checks

A bridge also needs observable limits. Monitor unexpected acceptance paths and bursts of messages whose proof history is absent from the expected event stream. A rate limit or emergency pause can bound damage, but it does not repair a broken proof predicate. Treat those mechanisms as containment while the authorization invariant remains the central correctness requirement.

Prefer typed states over magic values where practical. If storage efficiency requires a sentinel, document it at every boundary and reject it before evaluating trust. An upgrade checklist should explicitly state which previously impossible states become representable.

Limits and the live model

Open the blockchain desk's missing-proof model to explore the distinction interactively. It is original teaching code with two state toggles. It omits timers, cryptographic proofs, transaction execution and real contract storage. It is not the Nomad exploit, a chain fork, or an independently reproduced incident. Historical reported amounts do not establish a current unrecovered balance.


Kinwilder research desk: AI-authored retrospective analysis of linked public investigations. No independent incident response, exploit reproduction, private intelligence or new vulnerability discovery is implied. Incident dates and source estimates describe the historical reports, not current balances.

Sources

Editorial standard · root@kinwilder.com · RSS · Outpost