Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Replicated notarized block dropped when the leader refills the round, stalling the validator

Đang mở
#665 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
35/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
go

Hướng nghiên cứu

Start with simplex/epoch.go, especially processNotarizedBlock, handleBlockMessage, and createNotarizedBlockVerificationTask, then read the request handling in simplex/requestor.go. Reproduce the ordering race described in the issue by scheduling the notarized block task before storing a conflicting proposal. Done means the valid notarization is retained, the node advances to round R+1, and further proposals for R are ignored while the block is missing.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

medium security

Details

A dishonest round leader, who must be a current validator, can keep an honest validator stuck in one round. With 4 validators, the stuck node plus the withholding leader leaves no quorum, so the chain stops. The cause is createNotarizedBlockVerificationTask: it drops a certified block when e.rounds[R] is refilled, and it does not ask for the block again. The attack is a race, not a sure lock.

flowchart TD
  n1["dishonest round leader (validator)"]
  n2["handleBlockMessage"]
  n3["e.rounds[R] slot"]
  n4["createNotarizedBlockVerificationTask"]
  n5["victim validator stuck in round R"]
  n6["re-request of the notarized block"]
  n1 -->|"sends extra proposal for round R"| n2
  n2 -->|"stores it, refilling the slot"| n3
  n4 -->|"storeProposal refused"| n3
  n4 -->|"gives up, node stays in round R"| n5
  n6 -->|"not applied on this path"| n4
  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 component
  class n3 component
  class n4 vulnerable_code
  class n5 asset
  class n6 missing_control
  1. the round leader sends a decoy block to the victim and the real block B to the other validators. The others notarize B, which means 2f+1 votes certify it, while the victim holds only the decoy.
  2. the victim's processNotarizedBlock deletes the conflicting unnotarized round and schedules a verification task. The task runs later on the single verification goroutine, so the slot is only empty at scheduling time, not when the task runs. (simplex/epoch.go:2166-2177)
  3. the leader sends another proposal for the same round, queued ahead of the task. handleBlockMessage accepts it once the earlier task has cleared its in-flight flag, and nothing records that round R already has a notarization. (simplex/epoch.go:1984-1989)
  4. the task from createNotarizedBlockVerificationTask fails to store B and returns the zero digest. storeProposal refuses because e.rounds[R] now holds a block. Unlike the verify-failure branch, this path does not call ResendRoundRequest. (simplex/epoch.go:2412-2423)
  5. the requestor sends no new request for round R. The request timeout was already cleared, and observedSignedQuorum sends nothing once highestRequested is at least R. (simplex/requestor.go:140-148)
  6. the victim's empty-vote rebroadcast is the only way left to get B again, and each try faces the same race. Honest peers answer the rebroadcast with the notarization. A copy that finds the slot empty triggers a BlockDigestRequest and a new task, which the leader can again try to beat. (simplex/epoch.go:1004-1015)

Evidence

  1. simplex/epoch.go:2412–2423
  2. simplex/epoch.go:2166–2177
  3. simplex/epoch.go:1984–1989
  4. simplex/epoch.go:431–446
  5. simplex/requestor.go:140–148
  6. simplex/epoch.go:3697–3705
  7. simplex/epoch.go:1004–1015
  8. simplex/util.go:150–185

Impact

The victim stays in round R and votes in no later round while the attacker keeps winning. With 4 validators the chain commits nothing during the stall. A single leader can divert up to f victims, and it can repeat the attack each time it leads. This is a race, not a guaranteed lock: a buffered copy replayed by maybeLoadFutureMessages deletes the leader's block again. A response processed while no leader task is queued ahead lets B through. Nothing is disclosed, and no conflicting block is notarized. A finalization cannot rescue the victim, because 2f honest finalize votes are below 2f+1.

Reproduction steps

  1. The attacker is a validator that leads round R. It needs no action from the victim. It sends the victim a decoy block and the other validators the real block B, then keeps sending the victim proposals for R. Each copy of B that reaches the victim, replicated or fetched by digest, is scheduled behind one of those proposals. The attacker must win this ordering race on every recovery attempt. It can bias the race. It can resend one block, which OneTimeVerifier re-verifies instantly, or send distinct blocks to keep a task in flight. It also sees the victim's empty votes, so it knows when each rebroadcast cycle starts.

Recommended fix

(1) createNotarizedBlockVerificationTask refuses a verified block that carries a valid notarization for round R whenever e.rounds[R] holds any block, even an unnotarized one. It returns without re-requesting, so the certified block is lost and the node cannot leave R.

Fix criteria: A verified block with a valid notarization for round R ends up stored with that notarization, replacing any unnotarized block in the slot, or is re-requested until it is. Test it by scheduling the notarized-block task and storing a conflicting leader proposal before it runs. The node must persist the notarization and advance to R+1.

(2) After a mismatch deletes e.rounds[R], the node forgets that R already has a notarization. handleBlockMessage accepts new leader proposals for R, and the requestor's highestRequested gate stops later notarization copies from fetching the block.

Fix criteria: Once a valid notarization for round R is known, the node does not store or vote on further proposals for R. It keeps a request for the notarized block pending until the block is stored. A leader proposal for R sent after the mismatch is ignored. Each notarization copy received while the block is missing leads to a request or a live timeout.

Status on main

Re-checked against main at 90995e0 on 2026-10-26; still present:

In createNotarizedBlockVerificationTask (simplex/epoch.go:2419-2423), a storeProposal failure returns common.Digest{} without calling ResendRoundRequest. Only the verify-failure branch (epoch.go:2392-2398) and the queue-full branch (epoch.go:2200-2203) re-request. processNotarizedBlock deletes the conflicting round at scheduling time (epoch.go:2168-2177). handleBlockMessage (epoch.go:1915-2022) keeps no marker that round R has a known notarization, so a new leader proposal can refill e.rounds[R] before the task runs. No PR or issue found.


Severity: MEDIUM
Status: Open
Category: TOCTOU race condition
CWE: CWE-367
Repository: ava-labs/Simplex
Branch: main
Date created: 2026-10-26
Claude Security finding: https://claude.ai/security/findings/find_01V7wt29pkaVW2Seq83txZ3z

Ngôn ngữ chính
Go
Star
22
Fork
4
Merge trung bình
1 ngày 17 giờ
Pull request đã merge (30 ngày)
32

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của ava-labs/Simplex

Tất cả issue của ava-labs/Simplex

Issue tương tự

Thêm issue về Go

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.