Skip to main content

secp256k1-native CVE-2026-63410

MEDIUM
Observable Timing Discrepancy (CWE-208)
2026-10-30 GitHub_M
5.9
CVSS 3.1 · Vendor: GitHub_M
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Identify timing-observable signing oracle
  2. Delivery
    Submit repeated secret-scalar signing requests
  3. Exploit
    Measure scalar_multiply_ct timing variance
  4. Execution
    Correlate je/jne branch timing to scalar bits
  5. Impact
    Statistically 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.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
No patch listed yet 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – 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

Vendor (GitHub_M) PRIMARY 5.9 MEDIUM
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
vuln.today AI 5.9 MEDIUM

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.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
4.0 AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (GitHub_M).

CVSS VectorVendor: GitHub_M

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

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

EPSS Score
0.3%
Top 79% exploitable
Prevalence
Rare
pre-1.0 Ruby gem, no published RubyGems dependents, tiny footprint
Social Media
2
Sightings
Data Quality
5 sources
Confidence: Medium

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.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.3%
Patch available No
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact· derived
Medium
Technical Impact
Partial

Priority Score

30
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +30
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

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

cpe:2.3:a:sgbett:secp256k1-native:*:*:*:*:*:*:*:*

More in Ruby

View all
CVE-2017-17405 HIGH POC
8.8 Dec 15

Ruby before 2.4.3 allows Net::FTP command injection. Rated high severity (CVSS 8.8), this vulnerability is remotely expl

CVE-2017-17790 CRITICAL POC
9.8 Dec 20

The lazy_initialize function in lib/resolv.rb in Ruby through 2.4.3 uses Kernel#open, which might allow Command Injectio

CVE-2017-14064 CRITICAL POC
9.8 Aug 31

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

CVE-2016-2336 CRITICAL POC
9.8 Jan 06

Type confusion exists in two methods of Ruby's WIN32OLE class, ole_invoke and ole_query_interface. Rated critical severi

CVE-2026-77602 CRITICAL POC
9.9 Sep 23

Authenticated remote code execution in OpenC3 COSMOS (Ruby gem 'openc3' versions 5.1.0 through 7.2.1) lets any logged-in

CVE-2016-2337 CRITICAL POC
9.8 Jan 06

Type confusion exists in _cancel_eval Ruby's TclTkIp class method. Rated critical severity (CVSS 9.8), this vulnerabilit

CVE-2016-2339 CRITICAL POC
9.8 Jan 06

An exploitable heap overflow vulnerability exists in the Fiddle::Function.new "initialize" function functionality of Rub

CVE-2017-9225 CRITICAL POC
9.8 May 24

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

CVE-2026-27614 CRITICAL POC
9.3 Feb 25

Stored XSS in Bugsink error tracking tool before 2.0.13 allows unauthenticated attackers to inject persistent scripts th

CVE-2017-0898 CRITICAL POC
9.1 Sep 15

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

CVE-2013-4164 MEDIUM POC
6.8 Nov 23

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

CVE-2026-71847 HIGH POC
8.7 Aug 07

Heap-use-after-free in the Ruby json gem's native C extension (versions 2.20.0 through 2.21.1) allows an unauthenticated

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy