Skip to content

polygon/sync: ignore empty NewBlockHashes to prevent observer panic#21560

Merged
taratorio merged 3 commits into
mainfrom
yperbasis/polygon-empty-newblockhashes-panic
Jun 2, 2026
Merged

polygon/sync: ignore empty NewBlockHashes to prevent observer panic#21560
taratorio merged 3 commits into
mainfrom
yperbasis/polygon-empty-newblockhashes-panic

Conversation

@yperbasis

Copy link
Copy Markdown
Member

Summary

An empty NewBlockHashes packet (RLP 0xc0) decodes to a zero-length slice without error, so the surviving execution/p2p inbound path delivers it to observers unpenalized. The polygon/sync tip-events observer then indexed blockHashes[0] with no length check and panicked; observers run in a bare go observer(event) with no recover(), so the panic aborted the whole process — a remote, unauthenticated crash DoS on polygon/Bor nodes.

Fix: ignore announcements with no entries before any blockHashes[0] access.

Closes erigontech/security#72

Scope

Only the polygon/Bor astrid path (polygon/sync tip-events) is affected — it is the live consumer of inbound NewBlockHashes. On post-Merge Ethereum the eth multi-client drops these messages (#21505), so this is polygon-specific. peer_tracker's observer ranges over the slice and is already safe on empty; NewBlock decodes into a struct, so an empty packet is rejected at decode rather than reaching an observer.

Test plan

  • TestTipEventsEmptyNewBlockHashesDoesNotPanic — empty packet no longer panics the observer (red→green; the red failure was index out of range [0] with length 0 at tip_events.go:213)
  • TestTipEventsNewBlockHashesEmitsEvent — non-empty announcements still emit a NewBlockHashes event
  • go test -race ./polygon/sync/ (new tests, -count=5)
  • make lint clean; make erigon integration

Note

A recover() in common/event Observers.Notify would be complementary defense-in-depth — it would catch any future observer panic, not just this one — but per the issue it should not replace this targeted length guard.

🤖 Generated with Claude Code

An empty NewBlockHashes packet (RLP 0xc0) decodes to a zero-length slice
without error, so the surviving execution/p2p inbound path delivers it to
observers unpenalized. The tip-events observer then indexed blockHashes[0]
with no length check; since observers run in a bare go observer(event) with
no recover, that panic aborted the whole process — a remote, unauthenticated
crash DoS on polygon/Bor nodes.

Guard the observer: ignore announcements with no entries before any
blockHashes[0] access.

Closes erigontech/security#72

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash-DoS in Polygon/Bor tip-events processing by ignoring empty NewBlockHashes announcements before indexing into the slice.

Changes:

  • Add a length guard in the NewBlockHashes observer to avoid blockHashes[0] panics on empty packets.
  • Add tests to ensure empty announcements do not panic and non-empty announcements still emit NewBlockHashes events.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
polygon/sync/tip_events.go Adds len(blockHashes)==0 early-return to prevent slice indexing panic.
polygon/sync/tip_events_empty_newblockhashes_test.go Adds regression tests for empty and non-empty NewBlockHashes observer behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread polygon/sync/tip_events_empty_newblockhashes_test.go
… year

Address PR review feedback: the test cleanup now asserts te.Run exits with
context.Canceled instead of discarding the error (matching tip_events_test.go),
and the new file uses the current copyright year.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@Giulio2002 Giulio2002 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — obvious guard against empty NewBlockHashes packets, with focused regression coverage for the panic path.

@Giulio2002 Giulio2002 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — obvious guard against empty NewBlockHashes packets, with a focused regression test.

@taratorio taratorio enabled auto-merge June 2, 2026 01:19
@taratorio taratorio added this pull request to the merge queue Jun 2, 2026
Merged via the queue into main with commit bae1c11 Jun 2, 2026
89 checks passed
@taratorio taratorio deleted the yperbasis/polygon-empty-newblockhashes-panic branch June 2, 2026 02:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants