Share on social
October 8, 2026
Lorem ipsum
A flaw in GoBalance, a load-balancing tool used by many darknet sites, allows anyone to recover a site's master signing scalar from its publicly available data. With that key, an attacker can take over the site and redirect its visitors.
Between 5 and 7 October, both onion addresses of Dread, a prominent darknet forum, were taken over and redirected to a rival platform, Conclave. Several marketplaces using the same software were also affected. Dread's operators initially attributed the incident to an accidental key leak; the evidence set out below indicates that the GoBalance flaw was the more likely cause, at least for the second address.
This report sets out the sequence of events first, followed by background on how the affected software works and a technical analysis of the flaw.
All times are UTC. The account below is drawn from public statements and screenshots; claims made by either party could not be independently verified.
At approximately 05:31, a notice titled "dread²" appeared on Dread's primary onion address ("dreadytofat"), stating that the site had been hacked.

By 06:02, the same address displayed a message from the Conclave administrator claiming control of Dread's secret onion key. The attacker also claimed to hold sensitive data. If the GoBalance flaw was the method used, the attacker would have controlled the address but not Dread's servers or database; obtaining user data would have required a further step, such as intercepting traffic or phishing credentials. The address then alternated between the defacement notice and a thread discussing the breach.
Later that day, Dread's founder, HugBunter, published a transparency report attributing the breach to co-administrator Paris, stating that a software archive containing the private key had been uploaded by mistake. Paris issued a statement accepting responsibility and citing user error during a software deployment.



During the outage, administrators directed users to a secondary "VIP" mirror ("dreadlands"), an address previously reserved for premium members as a way around DDoS attacks. The announcement below was posted on an external forum.

HugBunter reiterated that the key exposure was an operational error rather than a flaw in Dread's infrastructure.

At approximately 02:29, a statement appeared on the "dreadlands" address disputing the administrators' account. Written in Russian, it argued that the takeover of a second, supposedly safe address showed the breach was not an accidental upload. It also contained veiled threats against the administrators, demanded an apology and compensation, linked to Conclave, and promised to publish details of the method later. A summary is given here rather than a full translation.

The compromise of this second address is significant. A single accidental upload would not explain the loss of two separate keys.
By 12:37, Dread's administrators had regained control of the VIP address and redirected it back to the legitimate site. HugBunter then acknowledged that the attacker had used a GoBalance zero-day against several darknet services. He stated that he did not believe user traffic had been intercepted, and maintained that the primary address had been lost through a separate key leak.
In the same post, he rejected the attacker's demands and published a partially redacted IP address said to belong to the Conclave administrator. Dread staff subsequently began promoting a newly generated onion address ("dreadohbles") through their official link channels.
HugBunter explained that despite the onion addresses being hijacked, Dread's servers had not been compromised and there was no evidence that its database had been accessed. However, he warned that a MiTM attack could not be completely ruled out and advised users to change their passwords on Dread and other potentially affected services as a precaution.
The vulnerability was traced to GoBalance, a tool used to manage Tor onion services. According to HugBunter, the flaw affects every released version and allows attackers to recover the signing capability needed to impersonate affected onion addresses without gaining access to the servers themselves. He also claimed that AI had been used to discover the vulnerability, with Dread's team using AI to identify the same issue during their investigation.
HugBunter also revealed that the attacker had claimed to possess Dread's database and attempted to extort him, but refused to provide any evidence. The repeated takeovers initially caused confusion among the administrators, who had struggled to understand how additional addresses could be compromised without any signs of a server breach.
Since the discovery, multiple darknet marketplaces have reportedly had their onion addresses taken over, including some that were already defunct. HugBunter warned that any service that had previously used GoBalance could potentially be affected. Dread's team announced plans to release a patched version and assist affected services in recovering their addresses or redirecting users to legitimate replacements.
HugBunter also confirmed that Dread would be carrying out a full operational security review and taking further steps to prevent additional takeovers. He acknowledged the damage the incidents had caused to the community's trust but insisted that Dread would continue operating despite the attacks.
An onion address is itself a public key, so whoever holds the matching private key controls the address. The GoBalance flaw lets anyone calculate that private key. No access to the site's servers is needed.
With the key, an attacker can:
The flaw does not by itself give access to the site's servers, database or stored user data.
Darknet markets and forums are frequent targets of DDoS attacks, often from competitors. OnionBalance spreads traffic for a single onion address across several backend servers, which makes such attacks harder. Dissatisfied with the pace of Tor's own DDoS defences, darknet operators developed EndGame, a toolkit that includes GoBalance, a re-implementation of OnionBalance in Go. The flaw described here was introduced in that re-implementation; the original OnionBalance and Tor itself are not affected.
When GoBalance signs a descriptor with a Tor-format key, it passes the signer only the first 32 bytes of the 64-byte expanded ed25519 key. The discarded half is the value that keeps each signature's nonce secret. Without it, the nonce becomes a fixed, publicly computable value, and each signature reduces to a linear equation whose only unknown is the secret scalar.
OnionBalance allows one v3 onion address to be served by several backend Tor instances.
Signing requires the service's master identity key, which comes in one of two formats:
Onion publications are not signed with the identity key directly. For each time period, Tor derives a blinded keypair from the identity key using a blinding nonce, and signs with the blinded key. This lets a client that knows only the address verify a descriptor without the master key being exposed. Both blinding and signing require the full expanded key, scalar and nonce prefix, in either format.
The descriptor signer branches on key format in pkg/stem/descriptor/hidden_service.go:
func blindedSign(msg []byte, identityKey gobpk.PrivateKey, blindedKey, blindingNonce []byte) []byte {
if identityKey.IsPrivKeyInTorFormat() {
return util.BlindedSignWithTorKey(msg, identityKey.Seed(), blindedKey, blindingNonce)
} else {
return util.BlindedSign(msg, identityKey.Seed(), blindedKey, blindingNonce)
}
}Both branches call identityKey.Seed(). In pkg/gobpk/gobpk.go, Seed() forwards to Go's ed25519.PrivateKey.Seed(), which returns only the first 32 bytes. For a Tor-format key, the value loaded from disk by pkg/onionbalance/tor_ed25519.go is the full 64-byte a ∥ h, so Seed() returns a and silently drops h.
The standard branch is unaffected: BlindedSign re-expands the 32-byte seed with SHA-512 and regenerates both a and h. The Tor branch assumes it has received the already-expanded key:
func BlindedSignWithTorKey(msg []byte, identityKey ed25519.PrivateKey, blindedKey, blindingNonce []byte) []byte {
esk := identityKey.Seed() // already truncated to 32 bytes; calling Seed() again has no effect
return blindedSignP2(esk, msg, blindedKey, blindingNonce)
}esk should hold 64 bytes (a ∥ h). It holds 32 bytes (a only), so the nonce prefix is lost before signing begins.
An ed25519 signature is a pair (R, S), where R = rB and:

Security depends on the nonce r remaining secret. Normally r = H(h ∥ M); because h is secret, so is r, and the equation has two unknowns (r and a), which cannot be solved.
Inside blindedSignP2, the code splits the expanded key and derives the nonce prefix from its second half:
s := decodeInt(esk[:32]) // the scalar a (correct)
k := esk[32:] // should be h, but esk is only 32 bytes, so k is empty
tmp := sha512.Sum512([]byte("Derive temporary signing key hash input" + string(k)))
kPrime := tmp[:32] // now a fixed, public constantWith k empty, kPrime is the SHA-512 of a fixed string: the same 32 bytes for every service and every descriptor. The nonce becomes r = H(kPrime ∥ M), and M (the signing certificate) is published in the descriptor. The nonce is therefore public.
That leaves a single unknown. An attacker who fetches a descriptor reads R, S, M, the blinding nonce and the blinded public key A′, and computes the blinded scalar:

Blinding multiplies the scalar by a factor t derived from the public blinding nonce, so it is reversed directly:

The result is the master identity secret scalar, sufficient to derive blinded keys and sign valid descriptors for the address in any time period.