firefox, go-ethereum, imagemagick, influxdb, micronaut-core, openbsd, proton, proxysql, sqlite, vim. All CWE-407.
4.5 KiB
go-ethereum — CWE-407 Disclosure Brief
2026-04-14 · Patch available — awaiting upstream merge
Finding
Two O(n²) defects in go-ethereum (Geth): one in filterLogs (log event filtering) and one in the legacy transaction pool authorization tracker. Both patched. Patches ready for upstream review. The filterLogs defect fires on every eth_getLogs range query and eth_newFilter subscription match; the txpool defect fires on every EIP-7702 authorization addition/removal.
The Defects
geth-0001 (PATCHED — HIGH): eth/filters/filter.go:510,521
// filterLogs — called per block during eth_getLogs and subscriptions:
if len(addresses) > 0 && !slices.Contains(addresses, log.Address) {
return false // O(A) linear scan per log entry
}
// ...
if !slices.Contains(sub, log.Topics[i]) {
return false // O(T) linear scan per topic slot per log entry
}
filterLogs calls slices.Contains(addresses, log.Address) (O(A) linear scan) and slices.Contains(sub, log.Topics[i]) (O(T) per topic) inside the per-log loop. With L logs, A filter addresses, and T topic entries, the function runs in O(L x (A + topics x T)). A typical DeFi indexer query spans thousands of blocks with hundreds of addresses.
go-ethereum-0001 (PATCHED — MEDIUM): core/txpool/legacypool/legacypool.go:1649
// lookup struct — authorization tracker uses []common.Hash:
auths map[common.Address][]common.Hash // linear slice for dedup
// addAuthorities — O(C) slices.Contains per tx:
if slices.Contains(list, tx.Hash()) { // O(C) where C = auths per address
continue
}
list = append(list, tx.Hash())
// removeAuthorities — O(C) slices.Index per tx:
if i := slices.Index(list, hash); i >= 0 { // O(C) scan
list = append(list[:i], list[i+1:]...) // O(C) shift
}
The lookup.auths map uses []common.Hash slices for per-address authorization tracking. addAuthorities calls slices.Contains (O(C)) and removeAuthorities calls slices.Index (O(C)) plus a slice splice (O(C)) for each transaction. With many EIP-7702 authorizations per address, both operations degrade quadratically.
Complexity Proof
geth-0001: At A=500 addresses, L=10,000 logs:
- Defective: 10,000 x 500 = 5,000,000 address comparisons
- Fixed: 10,000 x 1 = 10,000 map lookups
- 500x op reduction for DeFi/NFT indexing workloads.
go-ethereum-0001: At C=200 authorizations per address, N=1,000 txs:
- Defective addAuthorities: 1,000 x 200 = 200,000 hash comparisons
- Fixed: 1,000 x 1 = 1,000 map lookups
- 200x op reduction.
Impact
go-ethereum (Geth) powers the majority of Ethereum execution-layer nodes. The filterLogs defect (geth-0001) fires on every eth_getLogs RPC call and every eth_newFilter subscription match. DeFi protocols, NFT marketplaces, block explorers, and indexing services (The Graph, Dune Analytics) all rely on log filtering as a primary data retrieval mechanism. At scale, a single range query can span thousands of blocks with millions of log entries.
The txpool defect (go-ethereum-0001) fires on every EIP-7702 SetCode authorization, relevant as account abstraction adoption grows on Ethereum.
The Fix
geth-0001: Build map[common.Address]struct{} and map[common.Hash]struct{} lookup sets once before the per-log loop:
// Before
if len(addresses) > 0 && !slices.Contains(addresses, log.Address) { ... }
// After
// CWE-407 fix: O(1) map lookup instead of O(A) slice scan.
addrSet := make(map[common.Address]struct{}, len(addresses))
for _, a := range addresses { addrSet[a] = struct{}{} }
// ...
if _, ok := addrSet[log.Address]; !ok { ... }
go-ethereum-0001: Replace []common.Hash with map[common.Hash]struct{} for the auths tracker:
// Before
auths map[common.Address][]common.Hash
// After
// CWE-407 fix: map for O(1) dedup instead of O(C) slice scan.
auths map[common.Address]map[common.Hash]struct{}
Patch
defects/go-ethereum/patch/geth-0001-filter-logs-address-map.patch
defects/go-ethereum/patch/go-ethereum-0001-txpool-auths-map.patch
Unit tests: pass. geth-0001: 500x speedup at A=500, L=10K. go-ethereum-0001: 200x speedup at C=200.
What We Ask
- Confirm receipt and assign a GitHub Security Advisory or issue reference (ethereum/go-ethereum).
- Validate patches against your filter and txpool test suites.
- Assess severity: geth-0001 fires on every log query across all Ethereum infrastructure.
- Coordinate a disclosure date: we target 90 days from first contact.
Contact: see cover email. This brief is confidential until coordinated disclosure.