Coin Brief ENDE

What the key covers: three failures from values trusted beyond what they held

Three unrelated incidents from the past weeks share a shape worth naming. In each, software trusted a small stored value — a key, a cache entry, a number — to stand for something larger than what it actually encoded. Nothing was wrong with the cryptography, and in two of the three nobody wrote obviously bad code. The assumption simply expired, or never held in every case.

Algorand: an anchor that went stale on schedule. On 11 October the DNS root started being signed by a new key, KSK-2024, as IANA had long planned. Algorand nodes validate DNSSEC by default and carried their own copy of the root trust anchor. Nodes that were running kept working; any node that restarted could no longer validate and could not join the network until it ran version 5.0.3, published the next day with the new anchor. The stored value — "this is the root key" — was true when written and false on a known date.

Liquid: a cache key that left out the context. Blockstream's assessment of the 6 September theft from the Liquid federation traces it to Elements' rangeproof cache. Since 2018 the cache key omitted the asset commitment and script, so a proof verified in one context could be accepted in another. The summer fix added the missing fields but concatenated them without length prefixes, so a crafted byte sequence could still collide. Each cached "valid" stood for a check the node had not actually performed. About 4,000 BTC left the reserve; roughly 602 BTC are still outstanding, and peg-outs remain paused.

Bitcoin Core: a number that meant "forever". bitcoin-cli -rpcclienttimeout=0 is documented as "no timeout" and implemented as five years. On macOS, select() rejects anything above 10^8 seconds, and five years is about 1.58 × 10^8, so "no timeout" became "cannot connect". The fix backported to the 32.x branch caps the wait at about 24.8 days inside the socket code — a value that every platform can represent.

What the key covers: three failures from values trusted beyond what they held
What the key covers: three failures from values trusted beyond what they held — Coin Brief

The common lesson. In each case the bug was not in the main logic but in what a compact value was assumed to include:

  • a trust anchor includes today's root key — only until the rollover;
  • a cache key includes everything the result depended on — only if every field is bound, unambiguously;
  • a sentinel number includes "infinitely long" — only on platforms that accept it.

For anyone running crypto infrastructure, the checklist is short. Find every place where software ships its own copy of an external trust root and know who updates it. Treat cache keys in validation code as consensus code and require that they encode all inputs, with lengths. And when a "special" value stands in for a concept — zero for forever, an empty list for all — test it on every platform it will run on. The Liquid case shows the cost when the first two are missed together with an operational shortcut: a peg-out key kept online, with no limit on the size of a withdrawal.

Sources: go-algorand 5.0.3 — https://github.com/algorand/go-algorand/releases/tag/v5.0.3-stable ; IANA trust anchors — https://www.iana.org/dnssec/files ; Liquid incident assessment — https://blog.liquid.net/liquid-network-security-incident-assessment/ ; Bitcoin Core PR 36340 — https://github.com/bitcoin/bitcoin/pull/36340

Written by Victoria Shinder.