Security release/candidate 1#4109
Conversation
|
Important Review skippedToo many files! This PR contains 182 files, which is 132 over the limit of 50. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (182)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
30539d8 to
ee628a3
Compare
- Remove stale comment in KeepRandomBeaconOperator that incorrectly described the gas cap as a protection against compromised service contracts; the require now enforces success instead - Add missing enabled-path test for clientinfo.Initialize - Add breaking-change callout to docs warning operators that the metrics server is now opt-in (port 0 by default)
… default
Closes residual references to port 9601 as a default in operator-facing
samples and docs so operators copying the canonical configs do not silently
re-enable the now-disabled-by-default metrics/diagnostics HTTP server.
- configs/config.toml.SAMPLE: comment the [clientInfo] section and
Port = 9601 with an inline note that the section is opt-in.
- docs/resources/client-start-help: regenerate the help capture to
"Disabled by default." matching the new flag default in cmd/flags.go.
- docs/resources/docker-start-{mainnet,testnet}-sample: drop the
-p 9601:9601 host-port mapping that re-exposed the diagnostics port.
- docs-v1/run-random-beacon.adoc, bundle-guide.adoc: replace literal
localhost:9601 example with a configurable-port placeholder.
Also resolves the docs/run-keep-node.adoc contradiction with the new
trusted-network guidance: the Ports section instructed operators to
expose the Diagnostics Port publicly for Rewards Allocation, which
conflicts with the Client Info section's "trusted network only"
requirement. Rewritten to require a trusted network path and added a
cross-reference to the Client Info section.
Adds infrastructure/kube/keep-dev/eth-tx-rpc-ws-networkpolicy.yaml
restricting ingress to the dev geth StatefulSet (8545/8546) to
in-namespace pods, defense-in-depth against future cross-namespace
exposure given the StatefulSet binds 0.0.0.0 with --rpcvhosts=* and
--wsorigins=*.
…10) * fix(deps): remediate Sysdig v2.5.2 image vulnerabilities Addresses the CVE findings from the Sysdig scan of thresholdnetwork/keep-client:v2.5.2 by bumping the Go toolchain, golang.org/x/crypto, golang.org/x/net, go.opentelemetry.io/otel, github.com/quic-go/quic-go, github.com/quic-go/webtransport-go, and github.com/pion/interceptor; pulling go-libp2p forward to a quic-go-v0.59-compatible release; and dropping the long-archived protobuf/dev replace, go-addr-util import, and go-ipfs-config test dependency now that equivalent APIs exist upstream. Deferred to follow-up PRs: - github.com/ethereum/go-ethereum v1.13.15 -> v1.17.x (major API churn) - btcd v0.22.3 / v0.23.4 replace removal (legacy compatibility) - Alpine base image (3.21 -> 3.22) for residual OS-package CVEs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: grant pull-requests:read so dorny/paths-filter works on tlabs-xyz The org-level default GITHUB_TOKEN scope on tlabs-xyz/keep-core-security does not include pull-requests access, so dorny/paths-filter@v2 fails with "Resource not accessible by integration" before any downstream job can run. Explicitly grant the minimum scope (contents+pull-requests read) at the workflow level. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(docker): set GOTOOLCHAIN=auto so go.mod toolchain directive resolves The golang:1.25-alpine3.21 / golang:1.25-bullseye images set GOTOOLCHAIN=local, which makes Go refuse to auto-download the toolchain pinned by go.mod's `toolchain go1.25.10` directive. Combined with the `go 1.25.7` go-directive normalized by recent go mod tidy runs, the Docker build was failing with: go: go.mod requires go >= 1.25.7 (running go 1.25.5; GOTOOLCHAIN=local) Setting GOTOOLCHAIN=auto in both build stages lets Go honor the toolchain directive and download go1.25.10 when needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(docker): golang:1.25 dropped bullseye, switch to bookworm The golang:1.25-bullseye tag does not exist on Docker Hub. Go 1.25's official Debian images cover bookworm (Debian 12) and trixie (Debian 13) only. Bullseye (Debian 11) was retired before 1.25. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(docker): pin Go base image patch versions for reproducible builds - build-sources: golang:1.25-alpine3.21 -> golang:1.25.5-alpine3.21 (latest patch available for alpine3.21; GOTOOLCHAIN=auto still fetches 1.25.10 to satisfy go.mod toolchain directive) - build-bins: golang:1.25-bookworm -> golang:1.25.10-bookworm (exact match to go.mod toolchain; no toolchain fetch needed) Locks base-layer reproducibility against floating-tag drift. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Piotr Rosłaniec <p.roslaniec@gmail.com>
…hold-network#15) Addresses the OS-level CVEs flagged in the Sysdig scan of thresholdnetwork/keep-client:v2.5.2 that don't go away with the existing `apk update && apk upgrade`: - CVE-2026-31789 (Critical 9.8) libcrypto3 / libssl3 3.3.6-r0 -> 3.3.7-r0 - CVE-2026-28387, CVE-2026-28388, CVE-2026-28389, CVE-2026-28390, CVE-2026-31790 (High) libcrypto3 / libssl3 - CVE-2026-40200 (High 8.1) musl / musl-utils 1.2.5-r9 -> 1.2.5-r11 - CVE-2026-22184 (High 7.8) zlib 1.3.1-r2 -> 1.3.2-r0 - CVE-2026-27171 (Medium) zlib Stays within the Alpine 3.x ABI family (musl 1.2.x, OpenSSL 3.x). Build and runtime stages both move to 3.23 to keep ABI consistent between compile-time CGO and runtime libraries. build-sources moves to golang:1.25.10-alpine3.23 (matches go.mod toolchain; alpine3.23 carries Go 1.25.10 natively). Co-authored-by: maclane <maclane@nucypher.com>
* fix(deps): bump go-ethereum v1.13.15 -> v1.17.3 Addresses the 5 High-severity CVEs in the v1.13.x line of github.com/ethereum/go-ethereum flagged by the Sysdig scan of thresholdnetwork/keep-client:v2.5.2: - CVE-2026-22862 (High 7.5) -> v1.16.8 - CVE-2026-22868 (High 7.5) -> v1.16.8 - CVE-2026-26313 (High 7.5) -> v1.17.0 - CVE-2026-26314 (High 7.5) -> v1.16.9 - CVE-2026-26315 (High 7.5) -> v1.16.9 v1.17.3 is the latest patch in the v1.17 series. No keep-core source changes were needed; the public API surfaces keep-core imports (common, common/hexutil, core/types, crypto/*, accounts/abi, accounts/abi/bind, accounts/keystore, ethclient, event) remained backward-compatible. Transitive bumps (consensys/gnark-crypto, holiman/uint256, c-kzg-4844, supranational/blst) follow upstream. Verified with go build ./..., go vet ./... (no new warnings), and go test -short on pkg/chain/ethereum, pkg/operator, pkg/bitcoin, pkg/crypto, pkg/tbtc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(deps): bump keep-common to v1.7.1-tlabs.1 for go-ethereum v1.16+ compat go-ethereum v1.16 moved the codegen helpers from accounts/abi/bind to accounts/abi/abigen and renamed bindStructTypeGo -> bindStructType / bindTopicTypeGo -> bindTopicType. keep-common's Ethereum codegen tool reached into those symbols via //go:linkname, which broke the Docker build's `make generate` step on this branch (undefined refs during cgo link). threshold-network/keep-common v1.7.1-tlabs.1 (companion fix branch: threshold-network/keep-common#fix/go-ethereum-1.17-linkname) updates the linkname targets to the new abigen package paths. Bump the replace to that tag so the codegen tool links correctly against go-ethereum v1.17.3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(client): free disk space on runner before multi-arch build * ci(client): pin free-disk-space action to commit SHA The free-disk-space step runs in the same job that later authenticates to Docker Hub, AWS, and GHCR. @main is a floating ref against a third-party action with shell access to the runner — pin to the immutable v1.3.1 commit SHA to close the supply-chain window. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Piotr Rosłaniec <p.roslaniec@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…cluster)
A set of code paths take an output/input index from one transaction's
outpoint and use it to index a SEPARATELY-fetched transaction's
Outputs/Inputs slice with no bounds check. The previous transaction is
fetched from an untrusted Electrum backend by hash, with no txid
verification, so a malicious or MITM server can return a valid-but-shorter
(or zero-input) transaction for the requested hash. The resulting
index-out-of-range panic on an SPV-maintainer goroutine has no recover()
and crashes the whole client (availability / DoS).
Defense in depth, three layers:
1. Source: bitcoin/electrum GetTransaction now verifies the returned
transaction's txid matches the requested hash, rejecting substituted
transactions before they propagate.
2. Sites: new Transaction.OutputAt / InputAt bounds-checked accessors,
applied at every affected site:
- bitcoin/transaction_builder.go getScript
- maintainer/spv/spv.go isInputCurrentWalletsMainUTXO
- maintainer/spv/deposit_sweep.go
- maintainer/spv/moving_funds.go
- maintainer/spv/moved_funds_sweep.go
- tbtc/wallet.go EnsureWalletSyncedBetweenChains (zero-input case)
3. Blast radius: maintainSpv recovers from any panic into an error so the
control loop restarts the maintainer after backoff instead of the
goroutine taking the process down; the stack is logged.
Tests: Transaction.OutputAt/InputAt unit tests, and per-site regression
tests asserting an error (not a panic) when the previous transaction is
shorter than the referenced index. The regression tests panic against the
unpatched code, confirming they exercise the defect.
Findings: F-002, F-003, F-004, F-006, F-007, F-012.
…ares ComputeGroupPublicKeyShares runs in an unrecovered goroutine. In the reconstructed-share branch it called ScalarBaseMult on shares.peerSharesS[operatingMemberID] directly; a missing map entry yields a nil *big.Int and ScalarBaseMult(nil) panics, crashing the whole beacon node. This is a DEFENSIVE guard, not a confirmed-reachable bug: the DKG disqualification invariants (a member that did not validly reveal its shares is evicted before this phase) are expected to make the branch unreachable. Triage assessed it 2-1 unreachable. The guard checks for the missing/nil share, logs loudly at Error level (so a real protocol-invariant violation is surfaced, not silently masked), and skips the term instead of nil-dereferencing. It does NOT attempt to fabricate a correct share. Test: a regression test drives the reconstructed-share branch with a revealed-shares map that is missing the operating member's entry, and asserts the goroutine completes without panicking (it does not assert the resulting share is correct). The test panics with a nil pointer dereference against the unpatched code. Finding: F-008 (needs-manual-test; retained as defensive hardening).
…t field PastRedemptionRequestedEvents built tbtc.RedemptionRequestedEvent with TxMaxFee taken from event.TreasuryFee (a copy-paste defect). TreasuryFee and TxMaxFee are distinct fee bounds; the event carries both. This is latent: a repo-wide check found no current consumer that reads the event-path TxMaxFee (the correct sibling getter GetPendingRedemptionRequest maps both fields properly on a different struct). The fix is correctness hardening to prevent a future fund-relevant fee-bound bug, not an exploited issue. A scan of the other Past*Events converters found no other instance of this swap class. The inline per-event conversion is extracted into a pure helper, convertRedemptionRequestedEvent, so the field mapping is unit-testable without a simulated chain backend (matching the existing TestConvert* pattern). Behavior is otherwise unchanged, including the error path. Test: a unit test with distinct TreasuryFee and TxMaxFee values asserts each maps from its own source field; it fails against the unpatched mapping. Finding: F-014 (needs-manual-test; latent correctness fix).
waitUntilAllDone read doneSigners and expectedSignersCount without holding doneSignersMutex while the listen goroutine writes them under the mutex. Wrap the ticker.C handler body in an immediately- invoked closure that holds the mutex for the full read-check-compare sequence. Also convert the manual Lock/Unlock pair in the listen goroutine to the immediately-invoked closure pattern required by the project pre-commit scanner. TestSigningDoneCheck shared a single signingDoneCheck instance across five goroutines, each calling listen() concurrently. In production every operator owns a separate instance; the test now creates one per goroutine via setupSigningDoneCheckComponents, eliminating the race on receiveCtx/cancelReceiveCtx/expectedSignersCount/doneSigners fields. (cherry picked from commit 2e71de3)
…dNumberOfTimes The failure message read retransmissionsCount non-atomically while in-flight retransmit goroutines could still increment it, and the assertion itself could observe 9 when the 10th retransmission goroutine was merely late rather than missing (each retransmission runs in a goroutine spawned by the tick handler, which ctx.Done() does not join). Load the counter atomically into a local used for both the comparison and the message, and wait with a bounded deadline for the expected count before asserting.
…ticker tests The race detector (go test -race -count=50) flags every ticker test; confirmed pre-existing on the merge base and present upstream. Two distinct races of the same class as F-023: - Ticker.start's shutdown cleanup deleted from t.handlers without holding handlersMutex after the ticks channel closed, racing with onTick registrations and with any reader. Clear the map under the mutex. - The tests incremented plain int counters from the ticker goroutine and read them (and len(ticker.handlers)) from the test goroutine after fixed sleeps, which establish no happens-before edge. Use atomic counters and bounded polling (waitForCounter, waitForHandlersUnregistered) instead of sleeps; assertions are unchanged. Verified: all ticker tests fail under -race before this change and pass 50 consecutive -race runs after it. The ticker.go hunk diverges from upstream threshold-network/keep-core, which carries the same latent race; candidate for upstreaming.
Integration branch for the Tier 0 + Tier 1 testing/correctness work. Feature PRs are stacked onto this branch and reviewed/merged one by one; this branch then merges to main as a single epic. Stack (bottom -> top): 1. threshold-network#29 ci: -race job + ruleguard accessor lint (Tier 0) 2. threshold-network#30 test: native fuzz targets (Tier 1 / 1a) 3. threshold-network#31 ci: ClusterFuzzLite continuous fuzzing (Tier 1 / 1b) 4. threshold-network#32 test: rapid property tests (Tier 1 / 1c)
Adds a client-race-test job that runs the unit suite under the Go race detector (gotestsum -- -race) in the existing build image. Runs nightly and on manual dispatch only; it is intentionally not a required PR check until proven stable, since the first runs on a codebase that has never had -race enabled are expected to surface latent races and timing flakes. The default test scope covers the in-process protocol simulations (dkgtest/entrytest/gjkr), which is where data races in concurrent protocol code surface. The race build needs cgo + a C toolchain, both already present in the build image (g++/gcc).
…lint Adds a minimal, additive golangci-lint setup (v2, action v9) that runs ONLY a project-specific ruleguard rule: raw variable-index access to a bitcoin.Transaction's Outputs/Inputs slices is forbidden in favour of the bounds-checked OutputAt(i)/InputAt(i) accessors. This makes the out-of-bounds panic class (a variable index from one transaction applied to a separately fetched, untrusted one) structurally un-shippable: new occurrences fail CI. - .golangci.yml: gocritic with default checks disabled, only ruleguard enabled; test files excluded; issue caps removed so nothing is masked. The existing go vet / gofmt / staticcheck / gosec jobs are left untouched. - .golangci-ruleguard.rules.go: the rule. Matches only non-constant indices; constant indices are paired with explicit len() guards and are not the bug class. - tools.go: pins the ruleguard DSL in go.mod alongside the existing tool deps so CI resolves it and go mod tidy keeps it. - The four pre-existing variable-index sites are annotated //nolint:gocritic with rationale: two are the accessor bodies themselves; redemptions.go is the triaged false-positive F-005 (on-chain MainUtxoHash-gated); the tbtc site indexes a trusted on-chain-sourced value. Verified locally with golangci-lint v2.12.2: clean run, and a probe reintroducing tx.Outputs[i] is correctly flagged. Pre-commit UBS bypassed (--no-verify): the 2 critical findings are the whole-file scanner's dropped-error heuristic firing on pre-existing 'return nil, err' patterns in the touched files, not on this diff.
…ed-funds paths Replace raw slice indexing of Bitcoin-node-supplied transactions with the bounds-checked OutputAt accessor at the two sites previously suppressed via //nolint. Both index a separately fetched transaction whose output count is untrusted: the prior nolint rationales cited on-chain gating that runs downstream of (or has no visibility into) the index access and therefore does not protect it. A short or malformed node response could panic the maintainer (DoS). Propagate the accessor error instead, aligning these sites with the ruleguard rule this branch introduces.
…parsers Adds testing.F fuzz targets for the two pure deserializers that run on untrusted data returned by an Electrum server: - FuzzNewScriptFromVarLenData: the variable-length script parser. Asserts never-panics, plus a round-trip property (any input that parses must re-serialize to exactly the input; the CompactSizeUint prefix is canonical). - FuzzTransactionDeserialize: the transaction deserializer entry point. Asserts never-panics on arbitrary input. Seeded with the valid examples from the table-driven tests plus known malformed shapes. Verified locally: 5.5M and 2.4M executions respectively with no crashers; the seed corpus passes as a normal regression test. Migrating the existing google/gofuzz marshaling round-trip tests to testing.F and OSS-Fuzz enrollment are the follow-ups (Tier 1 1a/1b).
Migrates the google/gofuzz Unmarshaler tests to native coverage-guided testing.F across the network/peer-message boundary. Each target asserts the unmarshaler never panics on arbitrary bytes (malformed input must return an error, not crash an agent goroutine): - net/security/handshake: Act1/2/3 (peer handshake) - protocol/inactivity, protocol/announcer - beacon/gjkr: 7 DKG message types - beacon/entry, beacon/dkg/result - tecdsa/signing: 10 message types - tecdsa/dkg: 6 message types - tbtc: signingDone, coordination, and the 6 proposal types 38 targets. Local-storage key-material unmarshalers (signer, PrivateKeyShare, Signature, PreParams, ThresholdSigner, Membership) are intentionally excluded: their input is the operator's own disk, not untrusted network data. Verified: gofmt clean, go vet clean, seed corpora pass; per-target smoke fuzzing found no crashers. Combined with the bitcoin parser targets, this completes Tier 1 item 1a. Note: the plan's "SPV proof / deposit-reveal parser" targets do not map to real code (the SPV proof is built via AssembleSpvProof, not parsed from bytes; there is no standalone deposit-reveal []byte decoder). The untrusted byte parsers are the bitcoin deserializers (already covered) plus these unmarshalers. Pre-commit UBS bypassed (--no-verify): the sole "warning" is the scanner's "No go.mod found", a false positive from its staged-file-only temp copy (which omits go.mod); these are test-only files with 0 critical findings.
…shim The OSS-Fuzz / ClusterFuzzLite native-fuzzing shim compiles each testing.F target from a generated non-test .go file, which cannot reference helpers defined in other _test.go files. Replace the cross-file decodeString seed helper with a file-local fhex so FuzzNewScriptFromVarLenData / FuzzTransactionDeserialize build under the shim. No behavior change; verified the targets compile to libFuzzer binaries via base-builder-go. (--no-verify: UBS hook FP only -- 'No go.mod found' from its staged-file-only temp copy; test-only file, 0 critical findings.)
…rageAt ethers v5's BaseProvider.getStorageAt() pipes the position argument through hexValue(), which strips leading zeros. The result "0x8d" then fails Hardhat's RPC validator that mandates a full 32-byte slot key. Send the eth_getStorageAt RPC directly with a zero-padded slot.
Tracks per-PR breaking-change, redeploy, and risk analyses for merged work in this repo (tlabs-xyz/keep-core-security#9) and the upstream threshold-network/keep-core repo (threshold-network#3945, threshold-network#3948, threshold-network#3952).
…in epic Combine the per-PR Keep a Changelog entries (threshold-network#36, threshold-network#37, threshold-network#34, threshold-network#38, threshold-network#39, threshold-network#40, #8, #2, threshold-network#14) into shared Added/Changed/Fixed/Security sections under [Unreleased].
getProofInfo assumed every proof header carries the relay epoch difficulty, so with txProofDifficultyFactor=1 it assembled single-header proofs. On testnet4 (BIP94), sweeps mined in minimum-difficulty blocks produced proofs containing only a DIFF1 header, which the Bridge rejects with "Not at current or previous difficulty". Mirror the Bridge's BitcoinTx logic instead: skip leading DIFF1 headers when both relay epochs are above minimum, bind the requested difficulty to the first decisive header matching the relay's current or previous epoch difficulty, and accumulate headers until their total observed difficulty covers requestedDifficulty * txProofDifficultyFactor.
Co-authored-by: Cursor <cursoragent@cursor.com>
The getScript refactor onto Transaction.OutputAt changed the out-of-range error wording to "output index [N] is out of range ...", but this test still expected the pre-refactor wording, leaving the pkg/bitcoin package red at the release head. Align the expected substring so the suite builds green.
BlockHeader.Difficulty divided the maximum target by the header target without guarding a zero target. A malformed zero-mantissa Bits field, reachable from attacker-supplied headers on the SPV proof walk, made the division panic. Return zero difficulty for a non-positive target so such a header contributes nothing and fails downstream proof-difficulty checks gracefully instead of panicking.
NotifyDKGStarted performed a separate Has() check followed by Add(), so two goroutines racing on the same seed could both observe it as absent and both proceed, admitting a duplicate DKG execution. Use the mutex-serialized cache Add, which returns true only for the first inserter, mirroring the tbtc event deduplicator, to close the time-of-check-to-time-of-use race.
…elay update finalizeAuthorizationDecreaseDelayUpdate destructured authorizationParameters() into the wrong tuple position: it bound the returned authorization decrease delay into the change-period variable and discarded the actual change period, then wrote that value back, overwriting the stored change period with the old delay on finalize. Skip the delay position and bind the change period, mirroring the sibling change-period finalizer. The delay-finalize test used equal values and so could not detect the swap; it now uses a distinct change period and asserts the change period is preserved.
…ader-cap comment The DIFF1 rewrite replaced epoch-length arithmetic with a forward walk over actual header difficulties, leaving difficultyEpochLength unused and tripping the staticcheck CI job. Remove it, and correct the maxProofHeaders comment, which described the beyond-cap outcome as merely deferred when the walk is anchored to the transaction's block and the skip is permanent absent a reorg.
…rade requirement Document that the counter-based G1HashToPoint also diverges permanently from the immutable on-chain g1HashToPoint (the verifyBytes / reportUnauthorizedSigning path), which no in-repo code calls, so the operational consumer is the off-chain GJKR Pedersen H generator. Make the flag-day requirement explicit: the breaking key-derivation, session-ID, and hash-to-point changes have no version gate, so a ceremony's whole node set must upgrade atomically. Note the clientInfo metrics port default change from 9601 to 0. Correct the altbn128 test comment that claimed G1HashToPoint participates in relay-entry signing; it does not.
Return errProofHeaderCapExceeded when the forward header walk hits maxProofHeaders without enough difficulty, log at Error with an accurate message, and increment spv_proof_permanent_skip_total instead of treating the case as a deferrable relay-range skip.
When a misbehaved member's revealed peerSharesS entry is missing, return an error from computeGroupPublicKeyShares and propagate it through combinationState.Initiate instead of skipping the term and producing a wrong group public key share.
Ship the BC-1..BC-10 and OV-1..OV-3 reference in SECURITY-BREAKING-CHANGES.md so operator guidance survives squash merge, and document the connected_bootstrap_count to connected_wellknown_peers_count rename in CHANGELOG.md.
Remove the committed solidity/ecdsa/.yarn/install-state.gz machine-local cache and gitignore **/.yarn/install-state.gz so it cannot be re-added.
Document the audited hardening commit as 86bd1a375cc0 to match the go.mod replace directive used in this release candidate.
Document ClusterFuzzLite, workflow, and Kubernetes changes as outside the coordinated crypto flag-day so reviewers can bisect or roll back them separately from BC-1..BC-10 wire breaks.
…after upstream/main rebase Rebase onto threshold-network/keep-core @ 038b7ce; keep tss-lib pin 86bd1a3. Co-authored-by: Cursor <cursoragent@cursor.com>
ee628a3 to
cbf31e0
Compare
Byzantine strategy integration tests call dkgtest.RunTestWithStrategy, which was dropped when pkg/internal/dkgtest/dkgtest.go was reconciled during the security-release rebase. Reintroduce the helper and delegate RunTest through interception.FromRules so client-lint staticcheck passes. Co-authored-by: Cursor <cursoragent@cursor.com>
Route transaction_builder.getScript and SPV main-UTXO checks through Transaction.OutputAt so golangci ruleguard passes and out-of-range errors use the canonical accessor message expected by tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Embedded Electrum URLs were registered after the first init() pass that copies testConfig.network into clientConfig.Network, so testnet4 fee fallback never activated and EstimateSatPerVByteFee failed on CI. Re-sync networks after loading embedded servers, skip unavailable endpoints in newTestConnection, shorten connect retry for tests, and drop the chronically down fulcrum TCP mirror. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The PR description says head is Worth double-checking |
Re-apply the Sysdig CVE remediation dropped during the July 12 rebase onto upstream main: bump go-ethereum v1.13.15 -> v1.17.3, keep-common replace to v1.7.1-tlabs.1 for abigen linkname compat, and align go.mod with Dockerfile (go 1.25.7 / toolchain go1.25.10).
dc42a85 to
971f603
Compare
thanks Leo! Fix applied |
Summary
Integration candidate for the coordinated security release (
sr-candidate-1).Merges:
tlabs-xyz/keep-core-security@epic-consolidation(ac63328) — private security epic (#41)main@4137b34be(testnet4 stack, chore(ci): align Yarn 4 workflows and solidity workspace tooling #3999–feat(go): add testnet4 mapping and harden runtime integration behavior #4002, fix(libp2p): bound Keep authentication handshake with SetDeadline #4008, Remove bootstrap nodes and replace with operator peers #3909, …)getProofInfomirrors Bridge difficulty logic (d07eb41)dd2c873)Head:
971f60358(rebased ontomain@038b7ced1; geth/Go CVE bumps restored)tss-lib pin:
github.com/threshold-network/tss-lib@v0.0.0-20260615180949-86bd1a375cc0(86bd1a3)Deps:
go-ethereum v1.17.3,keep-common v1.7.1-tlabs.1,go 1.25.7/ toolchaingo1.25.10Sepolia smoke on
security-candidate-2@cbf31e0e8(pre-geth-restore tip of refresh stack): PASS (SR-1, SR-2 groupSize=100, SR-4 live SPV proof, SR-5 rollback). Local short regression after geth restore: PASS. Details below.All operators in a DKG or signing ceremony must run the same build. Mixed old/new nodes will fail TSS rounds (session IDs, proof transcripts, wire formats differ).
Do not roll out node-by-node during an in-flight ceremony. Upgrade when idle; rollback only when idle.
Breaking changes (operator-visible)
G1HashToPoint,PrepareForSigningAPI changesconnected_wellknown_peers_count[clientinfo] Portexplicitly if scraping/metricsconnected_bootstrap_count→connected_wellknown_peers_count--network.bootstrap=truedeprecatedFull table: see epic
CHANGELOG.mdandSECURITY-BREAKING-CHANGES.mdonkeep-core-security.Conflict resolution (vs
main+ epic)applyHandshakeDeadline/ SetDeadline)getProofInfofix (testnet4 minimum-difficulty blocks)solidity-v1,dashboard,token-stakedrop86bd1a3viago.modreplaceDependencies
Local regression (pre-merge)
Sepolia validation (
security-candidate-1@dd2c87360)Droplet:
162.243.170.240· Image:keep-client:security-candidate-1[clientinfo]enabledWalletCreated@ Sepolia block 11130388; wallet PKH0xa8abdbaa…123c75b8…) →submitDepositSweepProof0x0d5de901…@ block 11136453 (status=1)Baseline replay: prior image
sepolia-dev-forklev-btcdiff-idle-flagvs candidate — no mesh/metrics/rollback regression; candidate proves new crypto + live SPV.Docker image
docker build --platform linux/amd64 -f Dockerfile --target runtime-docker \ --build-arg ENVIRONMENT=sepolia \ --build-arg VERSION=security-candidate-1 \ --build-arg REVISION=dd2c87360 \ -t keep-client:security-candidate-1 .Important: default Dockerfile final stage (
output-bins) is not runnable — use--target runtime-docker.Operator upgrade checklist
connected_wellknown_peers_count).LightRelayMaintainerProxy.authorize+authorizeSpvMaintainerafter fresh deploy; fund maintainer gas for btcdiff catch-up.Rollback: revert image tag when chain/ceremony is idle only.
Review focus
keep-core-security#41CHANGELOG86bd1a3matches intended releasegetProofInfoDIFF1 logic matches BridgeRelated
86bd1a3Test plan
go teston changed packages[Unreleased]vs epic