BLOCKCHAIN AI.NEWS

Security · Analysis

Wormhole Is Closing a Way Out of Its Own Four-Day Quarantine

A patch filed this morning adds thirteen lines to the component that holds suspicious bridge transfers for four days. Without them, a message already in the holding pen could be looked at a second time, come back clean, and be signed early. The change is still unmerged — and the safety net it hardens is switched off by default.

Editorial illustration: a chrome holding chamber sealed behind frosted glass, beside a second identical doorway standing open with golden light spilling through
✓ No outlet has reported this. Primary sources only: wormhole-foundation/wormhole PR #4966, opened Sep 10, 2026, read with its diff and test file · Behaviour traced in node/pkg/notary/notary.go, node/pkg/p2p/p2p.go and node/cmd/guardiand/node.go at main · Contributor relationship per the Wormhole Foundation · 2022 bridge hack figures per Halborn and Bloomberg

At 13:33 UTC on September 10, a Wormhole contributor opened a pull request against the bridge's guardian node with a title that reads like a summary of its own problem: "node: Don't let reobservation bypass an active notary delay."

It adds sixty-three lines and removes none. Thirteen of them are the fix. The rest is a test.

The component in question is the notary, and its job is to be the thing that slows a suspicious transfer down. When Wormhole's transfer verifier looks at a token bridge message and cannot certify that the tokens backing it actually moved, the notary does not reject the message. It puts it in a queue and starts a clock. The clock, defined in the source as DefaultDelay, runs for four days. The comment beside it explains why: long enough "to allow for manual review and classification by the Guardians." A human is supposed to look.

The patch's author describes what could happen instead, in the pull request body: ProcessMsg "guards against already-blackholed messages but not already-delayed ones, so a message delayed as CouldNotVerify can re-enter via reobservation as Valid… return Approve, and be signed before its release time."

Why the same message shows up twice

Reobservation is ordinary machinery, not an attack. Guardians sometimes need to look at an on-chain event again — a node was behind, a request was missed, a chain reorganised. When they do, the message is fed back through the pipeline from the top.

The consequence is the part that matters here, and the patch spells it out in a code comment: "reobservation re-runs the transfer verifier from scratch, so the same message can re-enter with a different verification state." The second pass has no memory of the first. A message that could not be verified on Monday is simply a message being verified on Wednesday, and if it comes back Valid that second time, the old code had nothing to say about the four days it was supposed to be sitting out.

The existing code already understood this danger in one direction. A few lines above the new guard sits an older one for messages that have been blackholed — permanently refused — with a comment noting it is "important in case a message is reobserved or otherwise processed here more than once." The delay list never got the same treatment.

What a second look returns, before the patch

State on re-entry Old verdict Effect on a message already delayed
ValidApproveSigned before its release time
NotVerifiedApproveSame, where the verifier is disabled
Anomalous / Rejected / CouldNotVerifyDelayDelayed a second time; database and in-memory queue disagree on when it is due out
Any of the four, after the patchDelayOriginal release time preserved
Compiled by this desk from the verdict switch in node/pkg/notary/notary.go and the four cases enumerated in the new test, TestNotary_ReobservationDoesNotBypassDelay, in PR #4966.

The second row of that table is the quieter defect. When a delayed message is delayed again, delay() runs a second time and writes a fresh release time to the database while the in-memory queue keeps the original. Nothing escapes, but the node's two records of when a transfer comes out of quarantine stop agreeing — the sort of divergence that survives a restart and confuses whoever is reading the logs later.

Who could actually reach this

Here the story needs its brakes applied, because the ingredients for an alarming version of it are all present and the evidence for one is not.

A reobservation request does not arrive from the public. It travels the guardian gossip network as a SignedObservationRequest, and the handling code rejects it unless the sending address is in the current guardian set and the signature recovers to that same key. An address that is not a guardian gets an error reading "not in guardian set." There is also a fifteen-minute timestamp window, and an unimplemented TODO for per-guardian rate limiting.

So this is not a path an outside attacker walks up to. It is a gap in a defensive layer, reachable through machinery that is already restricted to the guardians themselves. The author's own branch name says as much: node/notary-reobservation-defence-in-depth. No advisory has been published, no CVE assigned, and nobody involved has suggested that funds were ever at risk. Neither has anyone said the opposite, because as of publication the pull request has eight requested reviewers and not a single comment.

The finding nobody outside can read

The pull request closes with a link to the document that prompted it. The filename is descriptive to the point of being a headline itself: manual-2026-06-30-notary-processmsg-missing-isdelayed-guard-lets-reobservation-bypass-delay.md, filed under findings/triaged/ in a repository called asymmetric-research/wormhole-llm-issues.

That repository returns a 404. The organisation exists; the repository is not public. Asymmetric Research is not an unknown quantity — it has been a Wormhole core security contributor for years, and the Wormhole Foundation awarded it a grant specifically to run the protocol's security engineering, audits, monitoring and bug bounty. A private findings tracker is exactly what you would expect such an arrangement to produce.

Two things are worth reading carefully and not past. The first is the date in the filename: June 30, seventy-two days before the patch was filed. The second is the prefix. In a repository whose name points at machine-generated issues, this finding is labelled manual-. The obvious story — an AI found a bug in one of crypto's most-used bridges — is the one the filename specifically does not support. What it suggests is a program that runs models across a codebase and keeps human findings in the same drawer, which is a duller and more believable picture of how this work actually goes. We cannot read the document, so that is as far as the inference goes.

A safety net that ships switched off

The notary is not old. It entered the tree on September 26, 2025, and notary.go has been touched seven times since. One of those was a November fix for a bug in which non-Ethereum messages were always approved — the same shape of defect as this one, a guard that did not cover every path into the function.

And in node.go, the flag that turns the whole thing on reads:

notaryEnabled = NodeCmd.Flags().Bool("notaryEnabled", false, "Run the notary")

False. A guardian runs the notary only by choosing to, and how many of the nineteen — MaxGuardianCount is fixed at 19 in the node's own source, with thirteen signatures needed to produce a valid attestation — have chosen to is not something the repository can tell you. That default is the strongest argument that this patch is hardening rather than an emergency. It is also the fact that makes the four-day delay less reassuring than it sounds, because a hold that has to be opted into is not a property of the bridge. It is a property of whichever operators switched it on.

The Take

The temptation with a story like this is to run it as a near-miss at the bridge that lost $325 million in 2022, and that would be dishonest. Nothing here is reachable by an outsider, nothing suggests exploitation, and the fix arrived through what looks like a functioning security program doing unglamorous work. Give maintainers the timing: seventy-two days from a triaged finding to a patch, on a defence-in-depth issue in an opt-in component, is not negligence. The genuinely interesting thing is structural. Reobservation exists because distributed systems need a way to look again, and looking again means state that was computed once gets computed twice, by code that has forgotten the first answer. Every guard the notary has — blackholed, and now delayed — is a patch for that same forgetting, added one at a time as somebody notices another door. The blackhole guard was written with a comment explaining precisely this risk, and the delay list still went a year without the equivalent. That is the part worth watching: not whether this particular gap mattered, but whether anyone has enumerated the rest of them, or whether the list is still being written one pull request at a time. We will update this story if the patch merges, or if Wormhole or Asymmetric Research says anything about it.

More on the subject