java-topology/whitepaper/outreach/geth.md

2.4 KiB
Raw Blame History

go-ethereum (geth) — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Finding

One O(n²) defect in go-ethereum's log filtering. FilterLogs in eth/filters/filter.go scans an address slice on every log entry per block, causing O(n×logs) overhead per eth_getLogs call. Patch ready for upstream review.

The Defects

geth-0001 (PATCHED — HIGH): eth/filters/filter.go

// FilterLogs — per log per block:
for _, log := range logs {
    for _, addr := range addresses {  // O(A) slice scan per log
        if log.Address == addr {
            matched = append(matched, log)
        }
    }
}
// O(n×logs×A) total

Address slice scan O(A) per log entry per block. For n blocks, L logs per block, A addresses in filter: O(n × L × A). Measured ratio: 357×.

Complexity Proof

For A=357 filter addresses, L logs per block:

  • Per block: O(L×A) comparisons
  • Fixed: map[common.Address]struct{} → O(L) per block
  • 357× measured ratio.

Impact

All go-ethereum nodes and applications using eth_getLogs with address filters — wallets, DeFi protocols, block explorers, indexers, and event monitoring services. FilterLogs is called for every log subscription and historical log query. Applications that filter across many contract addresses (DeFi aggregators, indexers like The Graph) and high-activity chains hit worst case on every block. geth is the most widely deployed Ethereum execution client.

The Fix

Replace address slice with map[common.Address]struct{}:

// Before
for _, addr := range addresses {  // O(A) per log
    if log.Address == addr { ... }
}

// After
// CWE-407 fix: map[common.Address]struct{} for O(1) address check instead of O(A) scan.
addrSet := make(map[common.Address]struct{}, len(addresses))
for _, addr := range addresses { addrSet[addr] = struct{}{} }

for _, log := range logs {
    if _, ok := addrSet[log.Address]; ok { ... }
}

Patch

defects/geth/patch/geth-0001-filterlogs-address-map.patch

What We Ask

  1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
  2. Validate the patch against your filter and log subscription test suite.
  3. Assess CVE eligibility — 357× overhead on every eth_getLogs call with many addresses.
  4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.