Honest builders never raise timestamp to parent's, so a leader's future timestamp voids honest proposals
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 43/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- go
- Ambito
- backend, distributed-systems
Direzione di ricerca
Read the builders and timestamp validation in msm/msm.go, starting with buildBlockOrTransitionEpoch and verifyTimestamp; then check the other builder paths at the cited locations for normal, collecting-approvals, Telock, and new-epoch blocks. Reproduce the stated case with a parent timestamped T+9s and verify the built block against its actual parent. Done means every honest builder's block passes VerifyBlock in that case.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Details
One Byzantine validator can stop honest leaders from getting blocks accepted, so the chain advances mostly through the attacker's own blocks. It needs only its normal turn as round leader. Honest builders stamp blocks with their own clock and never raise it to the parent's timestamp, so a future-dated parent makes their blocks fail verifyTimestamp.
flowchart TD
n1["Byzantine validator acting as leader"]
n2["honest builders in msm/msm.go (stamp raw sm.GetTime)"]
n3["verifyTimestamp"]
n4["honest leaders' proposals and chain progress"]
n5["clamp of timestamp to parent's"]
n1 -->|"future-dated block accepted"| n3
n2 -->|"child stamped below parent"| n3
n3 -->|"rejects honest blocks, rounds skipped"| n4
n5 -->|"not applied"| n2
classDef actor stroke:#2563eb,stroke-width:2px
classDef vulnerable_code stroke:#dc2626,stroke-width:2px
classDef existing_control stroke:#16a34a,stroke-width:2px
classDef missing_control stroke:#dc2626,stroke-width:2px,stroke-dasharray:5 5
classDef asset stroke:#9333ea,stroke-width:2px
classDef component stroke:#6b7280,stroke-width:1px
class n1 actor
class n2 vulnerable_code
class n3 existing_control
class n4 asset
class n5 missing_control
- Byzantine validator proposes a block stamped up to about 10 seconds ahead of real time on its turn as leader. The verifier accepts any timestamp up to
TimeSkewLimitahead, and production wiring sets noTimeSkewLimit, so the defaultmaxSkew = 10sapplies. (instance.go:570-591) verifyTimestampaccepts the future-dated block, which is then notarized. It rejects a timestamp below the parent's but allows one up tonow + timeSkewLimit. (msm/msm.go:526-540)- the next honest leader's builder stamps its child block with the raw local clock.
buildBlockOrTransitionEpochusessm.GetTime()and never raises it to the parent's timestamp, so the child is stamped earlier than its parent. (msm/msm.go:617-632) - the honest leader's
BuildBlockproposes the block without verifying it. The leader's own node does not runVerifyBlockon what it builds, so only other nodes catch the bad timestamp. (adapters.go:263-277) - honest verifiers reject the block with
errTimestampDecreasing.verifyNonZeroBlockrunsverifyTimestampfirst on every non-zero proposal, against the real parent. (msm/msm.go:498-504) - honest nodes empty-vote at once, so the round is skipped.
triggerEmptyBlockNotarizationis called on the verification failure, and the parent stays the attacker's block. (simplex/epoch.go:2227-2242) - Byzantine validator builds another future-dated child on its next turn.
LeaderForRoundis round-robin over round numbers, so the attacker leads again after a fixed number of rounds, skipped ones included. (simplex/epoch.go:3827-3830)
Evidence
- msm/msm.go:617–632
- msm/msm.go:1076–1077
- msm/msm.go:1477–1482
- msm/msm.go:526–540
- msm/msm.go:498–504
- external.go:62–81
- adapters.go:263–277
- simplex/epoch.go:2227–2242
- simplex/epoch.go:3827–3830
- instance.go:570–591
Impact
Honest leaders' proposals are rejected for up to TimeSkewLimit (10s) after each attacker turn. If the attacker's turns recur inside that window, honest leaders never land a block. The chain then advances only through attacker-built blocks, at a fraction of its normal rate, and the attacker picks every included transaction. No data is disclosed or changed, and every finalized block is valid.
Reproduction steps
- The attacker is a single Byzantine validator, which the report treats as the primary threat actor. It needs only its own round-robin turn as leader. Only a validator's signed leader proposal is processed. Whether the attack repeats without end depends on how soon the attacker's turns recur. That depends on validator-set size and network delay. With small validator sets a failed round ends after one network delay, so the attacker's turns can recur inside the 10 second window. Each turn is bounded by
TimeSkewLimit.
Recommended fix
The builders at msm/msm.go:588, :617, :1076 and :1478 stamp blocks with the raw local clock. The verifier requires timestamps that never decrease but accepts a parent up to TimeSkewLimit in the future. Honest builders therefore make blocks that honest verifiers reject.
Fix criteria: Every block an honest node builds passes verifyTimestamp against its actual parent, the block named by metadata.Prev, for example by using a timestamp at least the parent's. That parent is not the sealing block that buildBlockEpochSealed passes on. Test: with a verifier and an honest builder at time T, a block the honest builder builds on a parent stamped T+9s is accepted by VerifyBlock. Check this for normal, collecting-approvals, Telock and new-epoch blocks.
Status on main
Re-checked against main at 90995e0 on 2026-10-26; still present:
Every builder still stamps blocks with sm.GetTime() directly and never clamps to the parent's timestamp: msm/msm.go:588, 617, 1076 and 1478, via wrapBlock at msm/msm.go:1422. verifyTimestamp (msm/msm.go:526-541) rejects any block whose timestamp is below its parent's (531-533), but accepts timestamps up to now+TimeSkewLimit. The default limit is 10s (msm/msm.go:24, 232-233), and production wiring uses GetTime: time.Now (instance.go:571). No issue or PR tracks this.
Severity: HIGH
Status: Open
Category: Improper input validation
CWE: CWE-20
Repository: ava-labs/Simplex
Branch: main
Date created: 2026-10-26
Claude Security finding: https://claude.ai/security/findings/find_01PE8Rjj8nHkYYyQHYY372eT
- Lingua principale
- Go
- Stelle
- 22
- Fork
- 4
- Merge medio
- 1g 16h
- PR unite (30g)
- 35
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di ava-labs/Simplex
-
Unverified sealing-block finalization lets a validator redirect a syncing node's replication requestsForse già presa @yacovm l’ha presa 1 giorno fa. Apertalow security
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
ava-labs/Simplex#666 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Epoch discovery accepts a sealing block on a head count, letting low-stake validators forge epochsForse già presa @yacovm l’ha presa 1 giorno fa. Apertamedium security
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
Failed notarization WAL write lets a node sign both a finalize vote and an empty voteForse già presa @yacovm l’ha presa 3 giorni fa. Apertamedium security
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
I maintainer di solito rispondono entro 1 giorno
-
Builder ignores parent's P-chain height, so a leader's maximal height stalls honest proposalsForse già presa @yacovm l’ha presa 3 giorni fa. Apertamedium security
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
I maintainer di solito rispondono entro 1 giorno
-
Auxiliary-info store keeps unbounded data from any unauthenticated peerForse già presa @yacovm l’ha presa 4 giorni fa. Apertahigh security
Difficoltà 4/5 3-5 giorni Idoneità per principianti 56/100
ava-labs/Simplex#652 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di ava-labs/Simplex
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
lognorman20/monaco#7428 ·
-
docs(prompts): IF BLOCKED workflow-scope branch says to comment on the issue on jira/local trackersApertaagent-butler-finding bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
jordansmall/spindrift#6238 ·
I maintainer di solito rispondono entro 1 giorno
-
bug: microcks test get swallows test failure details and operation results in text output modeAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
microcks/microcks-cli#608 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug from-studio
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
esengine/DeepSeek-Reasonix#14868 ·
I maintainer di solito rispondono entro 1 giorno