Core-GethThe pages of this site follow this link

Core-Geth security audit

Core-Geth v1.12 security follow-up, August 2026

Core-Geth v1.12.23 measured at its tag against the advisory records: what it fixed, what it left open, and how its CVE identifiers reconcile.

Audit

Core-Geth Security Follow-Up: August 2026

  • Follows: 2026-03-security-audit.md
  • Subject: etclabscore/core-geth v1.12.23 (“Argos”), released August 14, 2026
  • Prepared by: The core-geth Authors
  • Agentic auditing methods and tooling: the strongest available Claude models at each stage of the work, February through September 2026
  • Work carried out by: White B0x
  • Work funded by: Ethereum Classic DAO
  • Method: direct measurement against etclabscore/core-geth at tag v1.12.23, and against the advisory records at OSV and the GitHub Advisory Database
  • Last edited: October 12, 2026

What operators need to do

Track releases at ethereumclassic/core-geth and upgrade to v1.13.0 or later. Every finding in this document and in the March 2026 audit is resolved there.

v1.12.23 is real security work, and it does not close the two findings that matter most to a node operator:

  • The Go toolchains are still Go 1.21 and, for the Arm archives, Go 1.22, twenty-four and eighteen months past end of life. Every node built from any v1.12.x release, including this one, carries whatever runtime vulnerabilities have accumulated since, independent of the client’s own code. Go toolchain lists the standard library advisories.
  • The eth_syncing regression introduced in v1.12.22 is untouched. #697 reports highestBlock incorrectly against the network head, which misleads exchanges, explorers and monitoring that read it to decide whether a node is synced.
  • One response cap in this release can disconnect peers that are answering correctly. The release corrects that class of error for account ranges and leaves it in place for storage ranges; see the finding below.
  • Its release notes carry no advisory identifiers, like v1.12.21’s, and v1.12.22’s notes attach CVE-2026-26315 to work the records assign to CVE-2026-26314.

The organization that owns the repository has published that it does not expect to continue this work. Its 2024 retrospective states:

“Without any way to obtain funding, the ETC Coop will be in maintenance mode, with spending minimized, until the funding runs out. At that time, it will be up to other stakeholders to take on any required maintenance of the ETC client, unless a new plan materializes.”

v1.13.0 is that continuation, developed in the open at ethereumclassic/core-geth. It carries the Go 1.26 toolchain, every CVE fix, the same p2p hardening series measured here, and the storage-range correction this release does not make.


Summary

A third release has been cut at etclabscore/core-geth since the March 2026 audit. v1.12.23 is substantive security work: 32 commits carrying a delayed-decoding hardening series for the p2p protocols, plus seven go-ethereum backports.

Two findings from the March audit are unchanged by it. The client remains on end-of-life Go toolchains: Go 1.21, now 24 months past, and Go 1.22 for the Arm archives, now 18 months past. The eth_syncing regression introduced in v1.12.22 is not addressed.

This document records what v1.12.23 contains, what it leaves open, and where v1.13.0 stands.


Status by release

This is the per-release picture across the three axes a node operator needs: the client’s own CVEs, the Go toolchain each archive was built with, and the regressions each release introduced. It is why “the latest v1.12.x is patched” does not hold. Every v1.12.x release, v1.12.23 included, leaves at least one client-side issue open, and every one stands on an out-of-support Go toolchain.

Finding Severity v1.12.20 v1.12.21 v1.12.22 v1.12.23 v1.13 line
CVE-2026-22862: ECIES decrypt length (remote crash; exploited on the Core-Geth v1.12 bootnodes, March 2026) High open fixed fixed fixed fixed
CVE-2026-26315: ECIES GenerateShared accepts an unvalidated key (node-key oracle) Medium open fixed fixed fixed fixed
CVE-2025-24883: off-curve point in UnmarshalPubkey High open open fixed fixed fixed
CVE-2026-26314: secp256k1 coordinate field-boundary bypass High open open fixed fixed fixed
CVE-2026-26313: P2P RLP item-count memory exhaustion High open open partial fixed fixed
CVE-2026-22868: KZG proof-verification DoS (not reached on ETC; active on the Ethereum Foundation networks the client also ships) Medium open open open open fixed
GraphQL query-depth DoS (endpoint off by default) Medium open open open open fixed
Go toolchain in support - no no no no yes
Go standard library advisories, all archives - 75 75 75 75 0 (go1.26.9)
eth_syncing highestBlock regression (#697) - not present not present introduced present not present
Snap storage-range cap can disconnect honest peers - not present not present not present present not present

Legend: fixed means the fix is present; open means not addressed; partial means the crash is prevented and a related denial of service remains.

v1.12.22, the release most often described as the CVE backport, did not close every finding. It fixed four of the six client CVEs and partly mitigated a fifth: CVE-2026-26313’s out-of-memory crash is prevented, but a peer can still make the node spend CPU on a message it will reject. It did not address the KZG denial of service or add the GraphQL depth limit, it introduced the eth_syncing regression, and it stayed on Go 1.21 and Go 1.22.

v1.12.23 carries the delayed-decoding hardening that closes CVE-2026-26313, and adds the storage-range cap in the row above. It does not touch the KZG path, the GraphQL limit, the eth_syncing regression or the toolchain.

None of the three emergency releases recommend rotating the P2P node key. The node-key oracle (CVE-2026-26315) they patch is the reason a node that ran v1.12.20 must rotate, so a patched node that kept its key is still running an exposed one. The March audit gives the procedure.

The Go standard library figure is the cross-archive union against the current database, 67 to 73 per archive. The v1.13.0 archives were built with go1.26.8 and carried none when the release shipped; the October 2026 Go batch has since reached go1.26.8 at module level, and v1.13.1 is built on go1.26.9, a scan of which reports none. The difference the table records is support: the v1.12.x toolchains will never receive any of these fixes. Go toolchain measures all of it.


What v1.12.23 contains

Measured across v1.12.22..v1.12.23: 32 commits, 71 files, +3,036 / -796 lines.

Delayed-decoding series. The release defers decoding of p2p message contents until after the message has been validated, so a peer cannot force allocation proportional to a claimed item count before anything has checked it:

Commit Change
b25f25cf1 rlp: add RawList for working with un-decoded lists
887da91c6 delay block body decoding until content validation
717942ef3 delay receipts decoding until content validation
de544c0c3 delay transaction packet decoding
4a2b0effc delay snap message decoding
4cdebb034 delay propagated block decoding until content validation
4a8cd33ea discard message before size check
0f8924182 validate responses against pending requests in p2p/tracker
ff7d98f1a fix crash in p2p/tracker clean when the tracker is stopped
85ac4d685 recalibrate snap account-range response item cap

Upstream backports. Seven changes from go-ethereum: #34787 (stop serving on unavailable responses), #34745 (drop peers sending invalid bodies or receipts), #34870 (batch index in deliver reconstruct), #34976 (snap error message), #33803 (embedded node size validation), #32210 (announcement drop logic), #30918 (prevent hanging dispatch).

The delayed-decoding refactor is adaptable to core-geth. go-ethereum’s rlp.RawList approach does not cherry-pick cleanly onto this codebase (13 merge conflicts), and v1.12.23 shows it can nonetheless be carried across with manual work.


What v1.12.23 does not change

The Go toolchains are unchanged and remain end-of-life. Measured at tag v1.12.23:

Location Value
go.mod go 1.21
.github/workflows/test-linux.yml go-version: '1.21'
Dockerfile FROM golang:1.22-alpine
build/checksums.txt version:golang 1.22.1

The published archives record what built them: go1.21.13 for Linux x86_64, macOS and Windows, and go1.22.1, the build/checksums.txt pin, for every Arm archive. Go 1.21 reached end-of-life in August 2024 and Go 1.22 in February 2025, and neither receives security patches. Every node built from this release inherits whatever unpatched runtime vulnerabilities its toolchain carries, independent of the client’s own code. This was the March audit’s finding and it is unchanged across all three 2026 releases.

The eth_syncing regression is not addressed. Issue #697, introduced in v1.12.22, reports highestBlock as incorrect relative to the network head. No commit in v1.12.22..v1.12.23 touches internal/ethapi/.

The cryptographic fixes from v1.12.21 and v1.12.22 are present and unchanged. Verified at tag: the ECIES public-key validation in GenerateShared, which v1.12.21 added, and the field-boundary check in crypto/secp256k1/curve.go, which v1.12.22 added, are both in place and byte-identical to this project’s own implementation.


Finding: one response cap in v1.12.23 can still reject honest peers

v1.12.23 recalibrates the AccountRange item cap and documents why: the previous value rejected honest responses. snapResponseLimits now reads

AccountRangeMsg:  2*maxRequestSize/common.HashLength + 1,   // 32769
StorageRangesMsg: maxCodeLookups * 10,                      // 10240
ByteCodesMsg:     maxCodeLookups,                           //  1024
TrieNodesMsg:     maxTrieNodeLookups,                       //  1024

with a comment deriving the AccountRange figure from the request tracker’s byte bound.

StorageRanges is bounded the same way and did not get the same treatment. Reading ServiceGetStorageRangesQuery at that tag, the server appends slots until size >= req.Bytes, with a hardLimit of req.Bytes * (1 + stateLookupSlack) above it. Neither is an item count. A storage slot costs a hash plus its value, so at least 33 bytes on the wire, and a 512 KiB budget therefore admits on the order of 15,900 slots before the byte bound stops the server, against a cap of 10,240.

The two caps that remain item-derived are correct: ByteCodesMsg and TrieNodesMsg are genuinely capped server-side at maxCodeLookups and maxTrieNodeLookups, so those numbers are the honest maximum.

Consequence. A peer answering a large storage-range request with small slots can exceed the cap without doing anything unusual, and is disconnected. This is the failure the AccountRange recalibration was made to fix, in the message type beside it.

This client carries no snap item ceiling at all. A response is matched against the pending request that produced it, in bytes for the two byte-bounded messages and in item count for the other two, so the bound is whatever was actually asked for. That cannot refuse an honest reply, which is the failure a fixed cap produces.


CVE identifier reconciliation

The advisory records assign these identifiers, verified against OSV and each fix commit confirmed in a full-history go-ethereum clone:

Identifier Issue Fix commit First release
CVE-2026-26313 · GHSA-689v-6xwf-5jf3 · GO-2026-4508 p2p message memory exhaustion (CWE-770) go-ethereum #33835 v1.17.0
CVE-2026-26314 · GHSA-2gjw-fg97-vg3r · GO-2026-4507 secp256k1 coordinate check (CWE-20) 895a8597c v1.16.9
CVE-2026-26315 · GHSA-m6j8-rg6r-7mv8 ECIES public key validation in the RLPx handshake 46bee92f9 v1.16.9

etclabscore/core-geth labels the secp256k1 issue CVE-2026-26315. That identifier belongs to the ECIES handshake issue. The correct identifier for the coordinate check is CVE-2026-26314. The label appears in commit 46bba8dfc, a doc comment and the Go test function name TestIsOnCurveRejectsCoordinatesAboveP_CVE_2026_26315 in crypto/secp256k1/curve_cve_test.go, the description of PR #696, the published release notes for v1.12.22, and a reply on issue #692. No commit, source file, pull request description or release note there uses CVE-2026-26314; that reply does, giving it to the ECIES fix in v1.12.21. The v1.12.21 and v1.12.23 notes carry no CVE identifiers.

Why this is easy to get wrong, and why it matters. CVE-2026-26313 and CVE-2026-26314 are published under the same title, “Go Ethereum affected by DoS via malicious p2p message”. They are distinguished by CWE class and fix commit, not by their titles. An operator matching advisory identifiers against release notes to decide whether they are exposed will not find CVE-2026-26314 addressed at etclabscore/core-geth, and may conclude it is outstanding when the underlying fix shipped in v1.12.22. Both issues are in fact addressed there.


Status of v1.13.0

v1.13.0 is released from ethereumclassic/core-geth, the repository created on December 21, 2024 under the GitHub organization that also hosts the ECIP repository. It is where contributions and release artifacts for this series belong. ETC Cooperative’s 2024 retrospective records that with the organization in maintenance mode, “it will be up to other stakeholders to take on any required maintenance of the ETC client”. Relative to v1.12.23 it carries the Go 1.26 toolchain upgrade and the dependency graph that requires, the six CVE patches with their tests, ETC network tooling, and the p2p hardening series. It is the current release series. It has about six months of testing on Ethereum Classic mainnet and Mordor behind it and a month in production since release, with no critical issue found.

Recommendation for operators is unchanged in direction and updated in target. Nodes on any v1.12.x release should upgrade to v1.13.0 from ethereumclassic/core-geth immediately. v1.12.23 is a safer position than v1.12.20 on both the cryptographic and p2p surfaces, and it does not resolve the toolchain exposure.


Supporting this work

The client is maintained by Ethereum Classic’s core developers and open community contributions, in the ethereumclassic GitHub organization. The Ethereum Classic DAO is the legal entity standing behind that work, and the floor under it when nobody else is paying. Mining pools, centralized exchanges, issuers of Ethereum Classic financial products, Etchash mining hardware manufacturers and large holders all depend on this client. If your operation relies on Ethereum Classic, please consider sponsoring its maintenance. Support this work says who maintains and funds it and how to sponsor it.


References

All Core-Geth audits and reports