DEV Community

Cover image for Qubic's Wallet Drain Traces Back to Predictable Randomness
Taha Echakiri for NeticsLabs

Posted on Originally published at blog.neticslabs.com

Qubic's Wallet Drain Traces Back to Predictable Randomness

TL;DR

  • Qubic is a layer-1 blockchain that runs fee-free transactions and smart contracts on a consensus mechanism called Useful Proof of Work, which redirects mining energy into training artificial intelligence models.
  • Between 23:42 UTC on 17 October and 01:26 UTC on 18 October 2026, an attacker drained 1,404 wallets of roughly 2.94 trillion QU, valued at about USD 1.4 million.
  • The wallets fell because their recovery seeds came from a generator with insufficient randomness. The project states the fault sat in its wallet software and that the chain protocol itself was not compromised.
  • Affected seeds were created in any browser on an iPhone or iPad, in Safari on a Mac until 18 October 2026, or in the Qubic iOS app before July 2025.
  • Qubic halted the chain at tick 85,371,949; 87.1 percent of the drained funds stayed on the network and froze in place, and exchange MEXC froze the account that received the other 12.9 percent within about an hour.
  • Web wallet version 4.26.4, dated 18 October, replaced JavaScript's Math.random() in seed creation with crypto.getRandomValues(). That fixes new seeds, and it leaves every seed already created in the old code as it was.

The 104-minute window and the wallets inside it

The attack ran for 104 minutes. Qubic's own statement puts the first drain at 23:42 UTC on 17 October and the last at 01:26 UTC on 18 October, and the count it published is 1,404 wallets holding roughly 2.94 trillion QU. Cointelegraph reports the haul at about USD 1.4 million.

Capture of Qubic's network explorer showing the chain's current tick counter, epoch summary and tick table

Qubic's own network explorer (explorer.qubic.org/network, captured 2026-10-19), which reports the chain's current tick and the tick table behind it, the counter Qubic used to name the halt point. Qubic halted the chain at tick 85,371,949.

A rate of roughly thirteen wallets a minute is the detail worth sitting with. As Netics reads it, once a seed can be derived, the work per wallet collapses to a computation. Wallet count then measures the size of the vulnerable population.

Qubic is a layer-1 chain that carries transactions and smart contracts without fees, built on a consensus design called Useful Proof of Work that repurposes mining energy for AI training workloads. Qubic halted the network at tick 85,371,949.

A seed generator built for animation timers

Qubic's account of the cause is one sentence long and it is the whole story: seeds were generated with insufficient randomness. crypto.news reports that the fix in web wallet version 4.26.4 replaced JavaScript's Math.random() in the seed-creation routines with crypto.getRandomValues().

Those two calls look interchangeable in a code review, and their guarantees differ. Math.random() is built for convenience: it produces a number that looks scattered, quickly, and it is specified without a promise of unpredictability. MDN's JavaScript documentation warns that it is not cryptographically secure and should not be used for anything related to security. crypto.getRandomValues() is built for unpredictability. It draws from the platform's cryptographic generator.

The distinction is old and it keeps costing money. crypto.news ties this incident to a class of failure researchers call Milk Sad, a faulty key-generation process that lets an attacker predict private keys, and Cointelegraph places it in a line that runs through Coldcard's July disclosure of wallets weakened by a firmware bug and, in 2023, Trust Wallet's browser extension and the Libbitcoin Explorer tool. Weak-seed failures form a recurring class, and Qubic is the latest case in it.

Netics diagram showing the Qubic fix as a before-and-after: Math.random() before version 4.26.4, crypto.getRandomValues() from 4.26.4

Netics editorial diagram: the change in Qubic's web wallet release 4.26.4, where seed creation moved from Math.random() to crypto.getRandomValues(), the browser interface built for cryptographic values.

The three environments Qubic named

Qubic listed the affected seeds by where they were created: any browser on an iPhone or iPad, Safari on a Mac until 18 October 2026, and the Qubic iOS app before July 2025. That list is more specific than most incident notices and it says something about how the vulnerability behaved.

If the defect were purely in one function, every environment would be equally exposed and the list would be unnecessary. The list implies a dependency on the platform underneath: the same call may have produced output of different quality depending on the engine that implemented it, and every entry on the list is an Apple platform. This reading is Netics analysis, and no source confirms it. Whether the underlying weakness came from the generator's seeding on those platforms or from the wallet's own use of it, the practical lesson holds. A key generator inherits the entropy of the runtime it runs in, and a browser is the runtime with the least control over that.

For a user, this is the uncomfortable part: the notice does not say which seeds are safe. Consulting the release notes tells you that new seeds are generated correctly. Nothing in the published material so far establishes that seeds created in the old code became safe once the code changed, because a seed is stored data and a code change does not rewrite it. Rotation is the only remedy that does not depend on an assumption.

What a validator halt can and cannot undo

Qubic stopped the chain, 87.1 percent of the stolen tokens stayed where they were and froze, and MEXC froze the account holding the remaining 12.9 percent in about an hour. That is an unusually complete containment for a crypto incident, and it is worth being precise about why it worked.

It worked because the asset never became bearer cash. Theft on a chain is a state change that the network agrees on, so a coordinated halt converts a completed theft into a pending one, and a centralised exchange converts an off-chain exit into a frozen account. Both moves need something that a bearer asset does not have: an authority that can act after the fact. Qubic has a way to halt its chain, and MEXC was able to freeze the receiving account.

The trade-off is on the record too. A chain that can be halted to protect funds can be halted for reasons its holders do not endorse, and the recovery decision now sits with a vote of the Computors. Qubic says a full technical report follows once a recovery plan is settled. Anyone treating this containment as a property of the asset class should read that report before generalising it.

Netics diagram with four tiles: 1,404 wallets drained, 2.94 trillion QU taken in 104 minutes, 87.1 percent frozen on chain, 12.9 percent sent to an exchange

Netics editorial diagram: the published numbers behind the Qubic drain, including the share of funds that stayed on the network and the share that reached an exchange.

What to check before you trust a key generator

The useful question for anyone who ships software that creates keys, seeds or recovery phrases concerns three things: which function produces the value, in which runtime it runs, and whether the answer stays unpredictable to someone who can read the code.

Four checks catch this class of bug before an incident report does:

  1. Name the API in the code review. A seed that comes from Math.random(), a language's default shuffle, a timestamp, or a hash of the device name is predictable by construction, whatever entropy the surrounding system claims to have.
  2. Check the source on every platform. The same call can behave differently across browser engines and OS versions, which is exactly what Qubic's three-environment list describes. Confirm that crypto.getRandomValues() is the source on each target runtime. A distribution test cannot prove that a generator is unpredictable: Math.random() can pass one while staying predictable to anyone who models its internal state.
  3. Treat a generator fix as a rotation event. Patching the code protects future seeds. It says nothing about the keys already written down, exported or stored, and those are the ones an attacker can work on at leisure.
  4. Write down the blast radius before the incident. Qubic could contain 87.1 percent because a halt was available and an exchange answered in an hour. Most systems do not, which makes early detection the only containment they own.

For teams in France and Morocco building products on top of key material, the same four checks map onto a procurement question that is easy to ask a supplier: which API generates our keys, on which runtimes, and how do we know the output is not reproducible. A vendor that cannot answer that in writing is asking you to take on the entropy risk without a description of it. We build and review exactly that kind of boundary in our security work, and the first output of the exercise is usually the answer to a question nobody had asked before.

Capture of Qubic's wallet release notes listing version 4.26.4 and its cryptographically secure seed generation fix

Qubic's own wallet release notes (github.com/qubic/wallet/releases, captured 2026-10-19), which list version 4.26.4 dated 18 October 2026 and the fix line naming cryptographically secure seed generation: the change that protects future seeds and leaves every earlier one untouched.


Originally published on the Netics blog.

Top comments (0)