secp256k1-native
CVE-2026-63410
MEDIUM
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessIdentify timing-observable signing oracle
-
DeliverySubmit repeated secret-scalar signing requests
-
ExploitMeasure scalar_multiply_ct timing variance
-
ExecutionCorrelate je/jne branch timing to scalar bits
-
ImpactStatistically recover secret key or nonce
Vulnerability Assessment
| Weakness |
CWE
ASVS 5.0
V6 - Authentication Timing attack prevention
|
| Exploitation Conditions | Exploitation requires a specific (source, compiler, flags) combination plus a downstream exposure, not a default remote condition: (1) the gem's native C extension must be compiled by an affected toolchain - GCC 14.3.0, 15.1.0, or 15.2.0 at -O2, which extconf.rb appends by default - causing GCC to reconstruct the branchless uint256_select into secret-dependent je/jne jumps; (2) a consumer must call Point#mul or the native scalar_multiply_ct on a secret private key or nonce; and (3) an attacker must be able to observe the timing of that operation, e.g. via an online signing oracle, and collect many repeated measurements for statistical recovery. Limiting factors that reduce realistic risk: builds using GCC ≤12.4.0 (pure bitwise ops) or GCC 13.3.0 (constant-time cmov) are NOT affected; the pure-Ruby path is unaffected and makes no constant-time claim; clang and GCC 16 were untested; version 0.18.0 removes the defect on all tested compilers; and the gem itself exposes no network surface, so network reachability depends entirely on the consuming application. |
| Impact | The input CVSS is 5.9 (Medium) with vector AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N - confidentiality-only, high attack complexity, no privileges or user interaction. No EPSS score is provided in the input, there is no CISA KEV listing (KEV=NO), and no confirmed working public exploit is present; the vulnerability was found internally via bare-metal dudect (|t|≈21) rather than an external weaponized PoC. SSVC-style signals are only partially present: the vuln.today decision label is 'this_month' (not act_now/emergency), which aligns with a serious-but-not-urgent cryptographic weakness rather than mass exploitation. The high C:H impact (recovery of a secret private key or nonce) is what drives the score upward, but AC:H and the narrow, consumer-dependent preconditions pull real-world priority down: the flaw only manifests in a binary built by specific GCC versions (14.3.0/15.1.0/15.2.0) at -O2 and only when a consumer calls Point#mul/scalar_multiply_ct on a secret scalar from a timing-observable context. The gem itself ships no network surface; the CVSS AV:N reflects an assumed downstream online signing oracle, so network reachability is consumer-dependent rather than intrinsic - this should be verified against the actual deployment. Net assessment: this is a legitimate cryptographic timing side-channel, not a high-CVSS-but-nonexistent-risk issue, but its practical priority is bounded by a tiny deployment footprint and strict compiler/exposure prerequisites. Missing data to note explicitly: no EPSS and no SSVC automatable/technical-impact fields were supplied, and the vendor itself states the affected-version grouping (only the 0.17.0 select idiom vs. earlier distinct CT issues) is unresolved. |
| Exploit ScenarioDerived | A downstream service uses secp256k1-native - built with GCC 14/15 at the default -O2 - to perform ECDSA-style signing with a secret key or nonce, and exposes an online signing oracle whose response timing an attacker can measure. Because the compiler reconstructed the branchless uint256_select into secret-dependent je/jne jumps in the Montgomery ladder, the attacker submits many signing requests and statistically correlates timing variation with scalar bits, progressively recovering the secret (the classic Brumley-Boneh setting). No confirmed public weaponized exploit exists at time of analysis; the vendor demonstrated the leak internally with dudect (|t|≈21) and ctgrind, and the high attack complexity (AC:H) reflects the large number of timing measurements required. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 30, 2026
Timing side-channel in secp256k1-native's native constant-time scalar multiplication (Point#mul and the native scalar_multiply_ct) lets an attacker who can measure operation timing statistically recover bits of a secret scalar such as a private key or nonce - but only when the C extension was built by GCC 14.3.0, 15.1.0, or 15.2.0 at -O2 (the level extconf.rb appends), where the compiler reconstructs the branchless uint256_select mask into a secret-dependent je/jne jump. The flaw is in the compiled binary rather than the source, so source review and ctgrind on a non-reconstructing toolchain miss it; builds with GCC 12.4.0 or earlier (pure bitwise ops) and GCC 13.3.0 (constant-time cmov) are not affected, and the pure-Ruby path is unaffected and separately makes no constant-time claim. Practical exploitation additionally requires a consuming application that multiplies a secret scalar in a timing-observable context such as an online signing oracle plus many repeated measurements; no public exploit code was identified at time of analysis, and version 0.18.0 removes the defect on all tested compilers.
RemediationAI
Vendor-released patch: upgrade to secp256k1-native 0.18.0 (https://github.com/sgbett/secp256k1-native/releases/tag/v0.18.0), which introduces a value barrier (ct_value_barrier_u64 via the ct_mask_u64 helper) on all nine constant-time mask-select sites and is re-verified as branch-free at every select line, ctgrind-clean and dudect |t| 0.68 mean across 20 runs on GCC 9.5-15.1; the fix landed in https://github.com/sgbett/secp256k1-native/pull/32 (commit a89bea1617a2d063c6545ad44565dc22098c880e) and vendor guidance is effectively to update to 0.18.0 from any earlier version because pre-0.17.0 releases carried separate constant-time issues. For users who cannot upgrade immediately, the advisory lists compiling the extension at -O0/-O1 or with a compiler that does not reconstruct the select, verified with objdump -dl - explicitly described as fragile and not recommended, and it does not address the earlier pre-0.17.0 issues; the other stated option is to avoid calling Point#mul on secret scalars (private keys or ECDSA-style nonces) from any timing-observable context, such as an online signing oracle, until patched. Because the defect lives in the compiled binary rather than the source, rebuilding with a known-good compiler and re-running the bare-metal dudect harness is the only way to confirm a given build is branch-free; the project has since made that statistical bare-metal run a required pre-tag release gate. Background documentation is at https://github.com/sgbett/secp256k1-native/blob/master/docs/advisories/0001-compiler-reconstructed-ct-branch.md.
Affects your stack
Find out whether the stacks and servers you run are on an affected version.
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The package is a Ruby gem wrapping a native C secp256k1 implementation; the affected component is the Montgomery-ladder secret-scalar path in the C extension. Ladder point selection uses uint256_select, deliberately written branchlessly as r = (a & ~mask) | (b & mask) with an all-zeros or all-ones mask. Under GCC 14.3.0/15.1.0/15.2.0 at -O2 the optimiser recognises this all-0s/all-1s select idiom, recovers the original boolean condition and emits a secret-dependent conditional jump whose taken/not-taken timing correlates with scalar bits flowing through the ladder - root cause class CWE-208 (Observable Timing Discrepancy), with CWE-1255 (compiler removal of a security-relevant code construct) also cited. The branchless select was itself introduced in 0.17.0 as the fix for the historical |t|=875 jp_add_internal infinity-branch leak, so the compiler regression silently undid that prior fix; the advisory notes that pre-0.17.0 versions had different constant-time issues rather than this select idiom. Reproducible verification on a bare-metal Zen 5 host showed dudect |t| ≈ 21 for scalar_multiply_ct_internal before the fix and a mean |t| of 0.68 after, with valgrind ctgrind reporting conditionals on uninitialised values at the uint256_select source lines beforehand and clean results afterwards. The 0.18.0 patch routes every constant-time mask through a value barrier (an empty volatile asm, the libsecp256k1/BoringSSL pattern) applied at nine mask-select sites; only uint256_select was observed to branchify under the tested compiler, the rest being hardened as defence-in-depth. The affected product is identified by CPE cpe:2.3:a:sgbett:secp256k1-native. GCC 16 and clang were untested and point releases, targets and flag combinations were not exhaustively bisected, so this is best treated as a (source, compiler, flags) property rather than a fixed version range.
Know when Ruby gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
AC:H because exploitation needs an affected compiler build plus many statistical timing measurements; PR:N/UI:N as the attacker only observes a signing oracle; C:H (key recovery), I:N/A:N; AV:N is consumer-dependent.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
DescriptionCVE.org
secp256k1-native is a native C secp256k1 implementation for Ruby. In affected native builds, native constant-time scalar multiplication through Point#mul or scalar_multiply_ct can leak timing information about a secret scalar when compiled by a toolchain that reconstructs branchless selection into a branch. The Montgomery ladder uses uint256_select with an all-zeros or all-ones mask, but affected GCC builds at -O2 recover the original condition and emit secret-dependent je or jne jumps whose timing correlates with scalar bits. This defeats the assumption behind the 0.17.0 jp_add_internal infinity-branch fix. A consumer must multiply a secret private key or nonce in a context where an attacker can observe timing; repeated measurements can statistically recover scalar bits. The defect is in the compiled binary, so source review or ctgrind on a non-reconstructing toolchain may miss it. GCC 14.3.0, 15.1.0, and 15.2.0 reproduced the branch reconstruction, and extconf.rb appends -O2. Tested GCC versions through 12.4.0 used bitwise operations and GCC 13.3.0 used constant-time cmov; the pure-Ruby path is not affected by this flaw and separately makes no constant-time claim. GCC 16 and clang were untested, and point releases, targets, and flag combinations were not exhaustively bisected. Earlier pre-0.17.0 versions had different constant-time issues rather than this introduced select idiom. Version 0.18.0 contains the verified fix. The advisory's broad pre-0.18.0 guidance also covers earlier, different constant-time issues; whether this CVE groups those issues or only the select idiom introduced in 0.17.0 remains unresolved.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.
Affected Products (CPE)CVE.org
Ruby before 2.4.3 allows Net::FTP command injection. Rated high severity (CVSS 8.8), this vulnerability is remotely expl
The lazy_initialize function in lib/resolv.rb in Ruby through 2.4.3 uses Kernel#open, which might allow Command Injectio
Ruby through 2.2.7, 2.3.x through 2.3.4, and 2.4.x through 2.4.1 can expose arbitrary memory during a JSON.generate call
Type confusion exists in two methods of Ruby's WIN32OLE class, ole_invoke and ole_query_interface. Rated critical severi
Authenticated remote code execution in OpenC3 COSMOS (Ruby gem 'openc3' versions 5.1.0 through 7.2.1) lets any logged-in
Type confusion exists in _cancel_eval Ruby's TclTkIp class method. Rated critical severity (CVSS 9.8), this vulnerabilit
An exploitable heap overflow vulnerability exists in the Fiddle::Function.new "initialize" function functionality of Rub
An issue was discovered in Oniguruma 6.2.0, as used in Oniguruma-mod in Ruby through 2.4.1 and mbstring in PHP through 7
Stored XSS in Bugsink error tracking tool before 2.0.13 allows unauthenticated attackers to inject persistent scripts th
Ruby before 2.4.2, 2.3.5, and 2.2.8 is vulnerable to a malicious format string which contains a precious specifier (*) w
Heap-based buffer overflow in Ruby 1.8, 1.9 before 1.9.3-p484, 2.0 before 2.0.0-p353, 2.1 before 2.1.0 preview2, and tru
Heap-use-after-free in the Ruby json gem's native C extension (versions 2.20.0 through 2.21.1) allows an unauthenticated
NVD
CVE.org
EPSS
Vulnrichment
GitHub
Exploit-DB