Background
How This Was Found
During Olympia upgrade preparation, the ETC core team needed Core-Geth as a reference client alongside Besu and Nethermind — both carrying ETC overlays for cross-client testing but not recommended for production. Core-Geth was the only existing ETC client at the time. That work confirmed what the commit history showed: the etclabscore/core-geth repository had not shipped a code release since v1.12.20 on June 10, 2024 — a 21-month gap. Multiple CVEs had accumulated unpatched, and the client was still shipping binaries built on Go 1.21, a runtime that reached end-of-life in August 2024.
Security disclosures sent to the upstream maintainer in February 2025 received no response. The last substantive upstream commit was the v1.12.20 release itself; the final commit of any kind was a GitHub Actions CI update on January 23, 2025. With Olympia requiring a reliable, patched client for network continuity, the ETC core development team brought Core-Geth forward under the ethereumclassic organization, applied all known patches, upgraded the Go toolchain to 1.26, and is preparing Core-Geth v1.13.0 for release ahead of the Olympia upgrade.
CVE Analysis
CVE Gap Analysis
The following vulnerabilities were present in etclabscore/core-geth at v1.12.20. All are patched in the ethereumclassic/core-geth codebase, pending release as v1.13.0.
Missing IsOnCurve check in UnmarshalPubkey — off-curve secp256k1 points pass deserialization without error, causing invalid results in any downstream ECDSA or ECDH operation.
Component: crypto/crypto.go — UnmarshalPubkey()
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: 8e40b7e41
ECIES Decrypt() length check used +1 instead of +params.BlockSize (16). Crafted RLPx auth messages with undersized ECIES payloads cause an out-of-bounds read — remote crash during P2P handshake, no authentication required.
Component: crypto/ecies/ecies.go — Decrypt()
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: dc73f2e4f
ECIES GenerateShared() accepted unvalidated ephemeral public keys into ECDH. A MAC-oracle attack using repeated unauthenticated RLPx handshakes can leak bits of the node's static P2P private key.
Component: crypto/ecies/ecies.go — GenerateShared()
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: 2d3528803
IsOnCurve() did not verify coordinates are strictly less than the curve prime P. Out-of-field coordinates satisfy the naive curve equation via modular arithmetic and bypass the validity gate, leading to undefined scalar multiplication results.
Component: crypto/secp256k1/curve.go — IsOnCurve(); C ext secp256k1_ext_scalar_mul()
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: 2d3528803
P2P message handler validated payload size (10 MiB cap) but not the number of RLP list items. A crafted header declaring millions of tiny items allocates per-item memory before validation — remote OOM crash via a single P2P message from any connected peer.
Component: eth/protocols/eth/handler.go + msgvalidate.go; eth/protocols/snap/handler.go
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: 5d0cb8b34
CVE-2026-22868MEDIUMPATCHEDKZG blob proof validation DoS — invalid proofs trigger full expensive cryptographic verification without disconnecting the offending peer, allowing sustained CPU exhaustion from any connected peer.
Component: core/txpool/validation.go — validateBlobSidecar(); eth/fetcher/tx_fetcher.go — Enqueue()
Affected: etclabscore/core-geth ≤ v1.12.20
Fix: 1419c5310
GraphQL Depth DoSMEDIUMPATCHEDNo query depth or complexity limit on the GraphQL endpoint (--graphql flag). Deeply nested queries exhaust CPU and memory. Compounded by GHSA-mh3m-8c74-74xh — a bug in graphql-go v1.3.0 where MaxDepth was silently non-functional.
Component: graphql/service.go; graphql-go v1.3.0 → v1.9.0
Fix: 6c2d383fa
Go Toolchain
Go Runtime End-of-Life
The upstream Core-Geth v1.12.20 release was built with Go 1.21, which reached end-of-life in August 2024. Go's release policy provides security patches only for the two most recent major versions. As of March 2026, Go 1.21 had been unsupported for 19 months, leaving the runtime's standard library (net/http, crypto/tls, encoding) unpatched across that window.
Core-Geth v1.13.0 at ethereumclassic/core-geth builds on Go 1.26 (current stable). The upgrade proceeded in two steps: Go 1.21 → 1.24 (removing the incompatible fjl/memsize dependency and fixing go vet format errors), then Go 1.24 → 1.26 (updating all golang.org/x/ dependencies for compatibility). The blst cryptography library was simultaneously upgraded from v0.3.11 to v0.3.16. Commit: 8385cf8e8.
Timeline
Release Timeline
Core-Geth v1.12.20 released at etclabscore/core-geth
Final upstream release — no code releases after this date
Go 1.21 reaches end-of-life
Build toolchain unsupported, runtime CVEs accumulate unpatched
Last upstream commit — GitHub Actions CI update
No code changes; repository effectively frozen
Security disclosures sent to upstream maintainer
No response received
All six CVEs patched at ethereumclassic/core-geth
CVE-2025-24883, CVE-2026-22862, CVE-2026-26315, CVE-2026-26314, CVE-2026-22868, CVE-2026-26313
Go toolchain upgraded 1.21 → 1.26
Commit 8385cf8e8; blst v0.3.11 → v0.3.16
Core-Geth v1.13.0 at ethereumclassic/core-geth (upcoming)
Pending Olympia network upgrade activation — Go 1.26, all CVEs patched, Olympia-ready
Risk Assessment
Risk Assessment
Remote crash via RLP (CVE-2026-26313)
Any peer on the ETC network can crash a node with a single crafted P2P message — no authentication, no prior relationship required.
Mitigation: Item count validation added in v1.13.0. Commit 5d0cb8b34.
P2P key oracle (CVE-2026-26315 + CVE-2026-26314)
Repeated unauthenticated RLPx handshakes with crafted ephemeral keys can leak bits of the node's static private key across the 21-month exposure window.
Mitigation: Patched in v1.13.0. Rotate the P2P node key (rm <datadir>/geth/nodekey) as a precaution on long-running nodes.
Remote crash via ECIES (CVE-2026-22862)
Off-by-fifteen length check in ECIES Decrypt() allows undersized ciphertext to trigger an out-of-bounds read during the RLPx handshake.
Mitigation: Patched in v1.13.0. Commit dc73f2e4f.
Go Runtime End-of-Life
Upstream Core-Geth shipped on Go 1.21, which reached EOL in August 2024. Runtime vulnerabilities in net/http, crypto/tls, and encoding accumulated unpatched for 19 months.
Mitigation: Core-Geth v1.13.0 builds on Go 1.26 (current stable as of March 2026).
Single unmaintained upstream
No response to security disclosures sent February 2025. The etclabscore/core-geth organization received no substantive code commit after June 2024.
Mitigation: Client transferred to the ethereumclassic org. Olympia multi-client architecture (Fukuii, Core-Geth, Besu) eliminates single-client dependency.
21-month release gap
The 21-month gap between v1.12.20 (June 2024) and the forthcoming v1.13.0 is the longest maintenance gap in ETC network history.
Mitigation: Protocol-funded maintenance path established via ECIP-1112 treasury.
March 2026
The March 2026 Attack
On 18 March 2026, CVE-2026-22862 was actively exploited against the ETC mainnet classic bootnodes ams3 and sfo3. Malicious P2P traffic sent crafted auth messages with undersized ECIES payloads, crashing each node on inbound handshake attempts. Because the crash occurred in listenLoop, the node process exited and restarted under the service manager — only to crash again on the next malicious connection, producing an automated crash-loop. Bootnode sfo3 accumulated 805+ restart cycles on v1.12.20 before the patch was deployed.
panic: runtime error: makeslice: len out of range
goroutine 42797 [running]:
github.com/ethereum/go-ethereum/crypto/ecies.symDecrypt(...)
crypto/ecies/ecies.go:224
github.com/ethereum/go-ethereum/crypto/ecies.(*PrivateKey).Decrypt(...)
crypto/ecies/ecies.go:322
github.com/ethereum/go-ethereum/p2p/rlpx.(*handshakeState).readMsg(...)
p2p/rlpx/rlpx.go:612
github.com/ethereum/go-ethereum/p2p/rlpx.(*handshakeState).runRecipient(...)
p2p/rlpx/rlpx.go:415
github.com/ethereum/go-ethereum/p2p/rlpx.(*Conn).Handshake(...)
p2p/rlpx/rlpx.go:308
github.com/ethereum/go-ethereum/p2p.(*Server).listenLoop.func2()
p2p/server.go:921Stack trace from issue #692. PR #694 (v1.12.21) was opened and merged in 5 hours — the first code activity from the upstream maintainer in 14 months.
Evidence Trail
Postmortem: Public Evidence Trail
The following issues and PRs at etclabscore/core-geth form a linkable evidence trail. Each was a missed opportunity to prevent the March 2026 attack.
geth version-check to surface CVE advisories
Filed by one of the core maintainers five years before the attack: add CVE tracking to version-check. Had it been implemented, the 2025–2026 advisories would have surfaced in every node operator's log.
Merge go-ethereum v1.14
Community maintainer prepared a full v1.14 merge, noted it was "ready for merge." Remained open through the March 2026 emergency.
Dependabot: bump golang.org/x/crypto 0.17→0.31
Automated tooling upgraded the exact dependency affected by CVE-2026-22862 — later exploited in production. Auto-closed when a newer version superseded it. No human reviewed it.
Support go 1.24 — includes CVE-2025-24883 fix
Community member @tornadocontrib explicitly referenced CVE-2025-24883 with a link to the advisory. Available for 9 months before the attack. Closed when contributor deleted their fork. No review, no response.
Automated: remove unresponsive bootnodes
Bootnode health check flagged deployed ETC bootnodes as unresponsive — some already experiencing intermittent crash-loops from early exploit probing.
Security vulnerabilities in go-ethereum affecting core-geth
Ledger security researcher publicly disclosed CVE-2025-24883, CVE-2026-22862, and CVE-2026-22868 on 4 February 2026. First maintainer response: 18 March 2026 — the day the attack began.
Olympia upgrade cross-client sprint — all CVEs patched and Go toolchain modernized
Preparing Core-Geth as a reference client for the Olympia multi-client upgrade required a full modernization sprint. Starting February 26, 2026, White B0x authored CVE-2025-24883, then the Go 1.21 → 1.24 toolchain upgrade (removing the fjl/memsize lock-in), the remaining five CVEs, and the Go 1.24 → 1.26 final upgrade — all on the white-b0x/core-geth main branch. The work was refactored into individually scoped PRs and published to ethereumclassic/core-geth on March 20–21, one per CVE, with test coverage and linked CVE references. This is the version of the patches that subsequently appeared in v1.12.22 without citation.
Release v1.12.21 ("Aegis") — emergency ECIES patch
Forced by active attack on bootnodes ams3 and sfo3. First code activity from @diega in 14 months. Three additional CVEs remained unaddressed.
Release v1.12.22 ("Hermes") — remaining CVE backports
Merged in under 2 minutes with no pre-merge review. Drawn from White B0x work publicly available since 20–21 March without citation. Go 1.21 EOL toolchain left unchanged.
Incorrect RPC eth_syncing response with v1.12.22
Regression introduced by the rushed v1.12.22: highestBlock reported incorrectly. Services relying on eth_syncing for sync status receive wrong data.
Root Cause
Structural Failures
Five independent structural failures — any one of which, if addressed, would have been sufficient to prevent the March 2026 attack.
No CVE Tracking Infrastructure
Issue #292 (2021) requested built-in CVE tracking in version-check. Never implemented. Operators had no automated signal that their client was exposed — they had to independently monitor the go-ethereum advisory database.
Automated Security PRs Unreviewed
Dependabot filed security bump PRs for golang.org/x/crypto and golang.org/x/net across January–April 2025, all unreviewed or auto-closed. PR #683 explicitly cited CVE-2025-24883 by name and was ignored for 9 months.
Single Point of Human Authority
@diega was the only person with merge access willing to cut releases. One community maintainer had a ready-to-merge PR (#649) but no merge rights. No governance path for security-critical changes without a non-reviewing approver.
Go Toolchain Lock-in
The fjl/memsize dependency was incompatible with Go 1.22+, locking the client to Go 1.21 (EOL August 2024). Three community PRs attempted partial fixes. The lock-in was known; it was not prioritized until it became a crisis.
Emergency Releases without Pre-release Testing
v1.12.21 was cut 5 hours after the PR opened; v1.12.22 was merged in under 2 minutes. The rushed process introduced the eth_syncing regression (issue #697, still open).
Recommended Client
Why Fukuii Is the ETC Client
The Core-Geth security failure was not a one-off — it was the predictable outcome of a Go-based client built outside the Ethereum Classic ecosystem, maintained under a corporate structure that has since wound down. Fukuii is the ETC-native execution client built from the ground up for Ethereum Classic. It does not share the Go toolchain, the go-ethereum P2P stack, or any of the code paths that were vulnerable in Core-Geth. Protocol-funded maintenance via ECIP-1112 provides a path not dependent on any single corporate entity.
Fukuii
RecommendedScalaEthereum execution layer client in Scala 3 — native Proof-of-Work consensus for ETC mainnet and Mordor, Engine API for ETH mainnet and Sepolia. One binary, four networks. The primary ETC client for the Olympia era.
- SNAP, fast, and regular sync for ETC and Mordor
- ETC mainnet, Mordor testnet, ETH mainnet, and Sepolia testnet
- Compatible with all major consensus clients
- Signed Docker images on GHCR
- JSON-RPC, Engine API, and MCP support
Quick Start
docker pull ghcr.io/chippr-robotics/fukuii:latestUse network=etc for mainnet, network=mordor for testnet, network=sepolia for Engine API.
Attribution
Prior Maintainers
Core-Geth is a fork of multi-geth, originally created and maintained by Wei Tang (@sorpaas). Multi-geth was the first multi-network go-ethereum fork with first-class ETC support, and its chain configuration architecture is the direct ancestor of core-geth.
The core-geth fork was then developed by ETC Labs until they left the ETC ecosystem in 2022. ETC Cooperative-paid staff maintained the client through the Spiral hard fork up until announcing maintenance mode for the client in December 2024:
- Isaac Ardis (@meowsbits) — primary architect and long-term maintainer
- Diego López León (@diega) — release manager; cut the v1.12.20 release
- Chris Ziogas (@ziogaschr) — contributor and maintainer
Migration
Network Migration Path
Core-Geth v1.13.x is the final stable release series of this client. The ETC network is migrating to Fukuii (github) as the primary ETC-native execution client. Core-Geth will continue to be maintained through the Olympia upgrade cycle to ensure a stable transition, but operators should plan their migration to Fukuii beyond that point.
If you are running etclabscore/core-geth v1.12.20 or earlier, upgrade to v1.12.22 immediately. Track ethereumclassic/core-geth for v1.13.0, which includes the Go 1.26 toolchain upgrade and full Olympia support.
Recommendations
Recommendations
Upgrade to v1.12.22 at etclabscore/core-geth immediately — it backports the critical CVEs. Then track ethereumclassic/core-geth for v1.13.0, which adds Go 1.26 and Olympia support. Nodes on v1.12.20 or earlier are exposed to remote crash (CVE-2026-26313, CVE-2026-22862) and potential key-oracle attacks (CVE-2026-26315).
Rotate your P2P node key as a precaution against CVE-2026-26315 exposure: rm <datadir>/geth/nodekey
Treat the upgrade to v1.12.22 as a security-critical patch, not a routine version bump. Track ethereumclassic/core-geth for v1.13.0, the full remediation with Go 1.26 and Olympia support. Begin planning migration to Fukuii.
Run multiple client implementations (Fukuii, Core-Geth, Besu) for cross-validation and redundancy during the transition.
Upgrade to v1.12.22 before re-opening the --graphql port on public-facing nodes.
Methodology
Methodology
These findings emerged from Olympia upgrade preparation. Core-Geth was required as a reference client alongside Besu and Nethermind, both of which carry ETC overlays for cross-client testing and are not recommended for production use. Fukuii is the only ETC-native production client and is built on Scala 3 / Pekko — it does not share the Go toolchain. The etclabscore/core-geth codebase at v1.12.20 was assessed against the go-ethereum GitHub Security Advisory database and the Go vulnerability database (vuln.go.dev). Each advisory was verified for applicability to core-geth's shared codebase and manually ported or cherry-picked where upstream structural differences prevented a clean merge. All patches were validated through Mordor testnet deployment and automated test suites across the Olympia reference client set (Core-Geth, Besu, Nethermind).
References
References
- ethereumclassic/core-geth — patched v1.13.0
- etclabscore/core-geth — upstream (unmaintained since June 2024)
- Full audit report — docs/audits/2026-03-security-audit.md
- go-ethereum GitHub Security Advisories
- Go Vulnerability Database — vuln.go.dev
- ETC Node Clients
- Olympia Client Implementations
- ECIP-1112: Treasury Funding for Protocol Maintenance