CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-26007

Living on the Edge: Subgroup Attacks in Python Cryptography

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 10, 2026·6 min read·345 visits

Executive Summary (TL;DR)

Missing validation in `pyca/cryptography` allowed attackers to force operations into small subgroups on binary curves (SECT), leading to private key recovery via the Chinese Remainder Theorem.

A high-severity flaw in the standard Python `cryptography` library allows attackers to recover private keys when using binary elliptic curves. By exploiting missing subgroup validation, malicious actors can perform Small Subgroup Attacks to leak private key bits via ECDH key exchange.

The Hook: The Titan Stumbles

If you are writing Python and you need to encrypt something, you don't roll your own crypto (unless you have a death wish). You use pyca/cryptography. It is the bedrock of the Python ecosystem, underpinning giants like Ansible, Paramiko, and seemingly every secure web framework in existence. It promises 'cryptographic recipes and primitives' that are safe by default. Ideally, it hides the foot-guns of OpenSSL behind a nice, rusty memory-safe abstraction.

But even the sharpest tools get dull. CVE-2026-26007 isn't a memory corruption bug or a buffer overflow; it's a logic failure in the mathematical plumbing of Elliptic Curve Cryptography (ECC). Specifically, the library forgot that not all points on a curve are created equal. By failing to check if a public key belongs to the safe part of the curve, the library opened the door to a classic cryptographic attack we thought we'd left in the 90s.

This vulnerability specifically targets binary curves (the SECT family). While modern cryptographers largely ignore these in favor of prime curves (like P-256 or Curve25519), legacy systems in banking and government still rely on them. If you're one of those unfortunates, your private keys might not be private anymore.

The Flaw: The Curse of the Cofactor

To understand this bug, we have to talk about the shape of an elliptic curve. A curve forms a group of points. The total number of points is called the order ($N$). For a curve to be cryptographically useful, we want to work in a subgroup of prime order ($n$). Ideally, $N = n$. This is true for prime curves like NIST P-256.

However, binary curves (like SECT283K1) have a property where the total points $N$ is not prime. Instead, $N = h \cdot n$, where $h$ is a small integer called the cofactor. Usually, $h$ is 2 or 4. This means the curve contains the massive prime subgroup we want to use, but it also contains tiny, parasitic subgroups of order $h$ (and divisors of $h$).

The vulnerability is simple: pyca/cryptography checked if a point was on the curve, but it didn't check if the point was in the correct subgroup.

Imagine a club (the Curve) with a VIP section (the Prime Subgroup) and a broom closet (the Small Subgroup). The bouncer (the library) was checking tickets to see if people belonged in the club, but forgot to stop people from sneaking into the broom closet. If an attacker forces your cryptographic operations into the broom closet, the math breaks down because the space is too small to hide secrets.

The Code: Rust in Peace

The flaw lived in the Rust backend of the library (src/rust/src/backend/ec.rs). When loading a public key, the library would defer to OpenSSL. However, it wasn't being paranoid enough about the inputs.

Here is the logic prior to the fix. It essentially trusted that if the point coordinates satisfied the curve equation, everything was fine:

// PRE-PATCH PSEUDOCODE
// We have coordinates (x, y)
let point = EC_POINT_new(group);
EC_POINT_set_affine_coordinates(group, point, x, y, ...);
// As long as it's on the curve, we are good to go.
if EC_POINT_is_on_curve(group, point, ...) {
    return Ok(point);
}

The fix, authored by Paul Kehrer and Alex Gaynor in commit 0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c, introduces a strict check on the cofactor. If the curve has a cofactor greater than 1, it forces a full key check:

// THE FIX (Commit 0eebb9d)
let mut cofactor = openssl::bn::BigNum::new()?;
ec.group().cofactor(&mut cofactor, &mut bn_ctx)?;
let one = openssl::bn::BigNum::from_u32(1)?;
 
// If cofactor != 1, we MUST verify the order
if cofactor != one {
    // This calls OpenSSL's EC_KEY_check_key which verifies n * P = Infinity
    ec.check_key().map_err(|_| {
        pyo3::exceptions::PyValueError::new_err(
            "Invalid EC key (key out of range, infinity, etc.)",
        )
    })?;
}

> [!NOTE] > Why not check every time? > Performance. Full validation (check_key) involves scalar multiplication, which is expensive. Prime curves (cofactor=1) don't need this check because they don't have small subgroups.

The Exploit: Death by a Thousand Cuts

How do we weaponize this? We use a Small Subgroup Attack (specifically a Lim-Lee style attack). This is most devastating in Elliptic Curve Diffie-Hellman (ECDH).

The Setup:

  1. Victim: Has a static private key $d$.
  2. Attacker: Wants to steal $d$.

The Attack Chain:

  1. The attacker creates a malicious public point $P'$ that lies in a small subgroup of order $k$ (e.g., $k=13$).
  2. The attacker sends $P'$ to the victim during a handshake.
  3. The victim computes the shared secret $S = d \cdot P'$.
  4. Because $P'$ has order 13, the result $S$ is also one of only 13 possible points. It repeats every 13 increments of $d$.
  5. The attacker intercepts the output (or infers it from the derived session key) and identifies which of the 13 points matches.
  6. The attacker now knows $d \pmod{13}$.

The Finale: The attacker repeats this process with points of order 17, 19, 23, etc. Once they have collected enough congruences ($d \pmod{k_i}$), they use the Chinese Remainder Theorem (CRT) to stitch them together and recover the full private key $d$.

It is like guessing a combination lock number. Instead of guessing 1,000,000 possibilities, you figure out the last digit, then the second to last, and so on, until the door opens.

The Impact: Why Should You Panic?

If you are using NIST P-256, P-384, or P-521, you can relax. These are prime curves with a cofactor of 1. You are immune by design.

However, if you are working in environments that mandate Binary Curves (e.g., SECT571K1, SECT283R1), this is a critical severity issue. These curves are often found in:

  • Legacy banking infrastructure.
  • Old government/defense communication standards.
  • Hardware that lacks efficient prime-field arithmetic.

For these users, an attacker can passively recover long-term private keys. Once the key is gone, the attacker can decrypt past traffic (if no forward secrecy was used) or impersonate the server indefinitely. The only saving grace is the complexity: the attacker needs to perform multiple handshakes to extract the full key.

The Fix: Banishing Binary

The immediate remediation is simple: Upgrade to cryptography version 46.0.5. This version includes the Rust-side fix that explicitly validates group order for curves with cofactors.

But the developers of pyca/cryptography went a step further. They aren't just patching the hole; they are condemning the building. In this release, all SECT curves have been deprecated.

This is a clear signal from the maintainers: Binary curves are dangerous, brittle, and rarely used in modern stacks. The ultimate fix is to migrate your infrastructure to Curve25519 or P-256. If you are still using SECT curves in 2026, you have bigger architectural problems than just this CVE.

Official Patches

pycaOfficial GitHub Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
8.2/ 10
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Affected Systems

Python applications performing ECDH using `cryptography`Systems utilizing Binary Elliptic Curves (SECT family)Legacy banking or government communication protocols

Affected Versions Detail

Product
Affected Versions
Fixed Version
cryptography
pyca
< 46.0.546.0.5
AttributeDetail
CWECWE-345 (Insufficient Verification of Data Authenticity)
CVSS v4.08.2 (High)
Attack VectorNetwork
Attack ComplexityHigh (Requires specific curve usage)
Privileges RequiredNone
ImpactPrivate Key Extraction

MITRE ATT&CK Mapping

T1557Adversary-in-the-Middle
Credential Access
T1040Network Sniffing
Credential Access
CWE-345
Insufficient Verification of Data Authenticity

Known Exploits & Detection

Lim-Lee Attack PaperFoundational paper on small subgroup attacks

Vulnerability Timeline

Vulnerability Disclosed
2026-02-10
Patch Released (v46.0.5)
2026-02-10
GHSA Advisory Published
2026-02-10

References & Sources

  • [1]Patch Commit
  • [2]SafeCurves: Small-subgroup attacks

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 3 hours ago•GHSA-4PH6-MJV7-3FQ6
6.5

GHSA-4PH6-MJV7-3FQ6: Improper Handling of Untrusted DNS-over-HTTPS Response Data in netfoil

netfoil, an allowlist-based DNS proxy, failed to sanitize ALPN fields parsed from untrusted DNS-over-HTTPS (DoH) HTTPS Resource Records. This allowed attackers to inject ANSI escape sequences into log files or trigger Denial of Service (DoS) via uncontrolled memory allocations.

Alon Barad
Alon Barad
3 views•6 min read
•about 4 hours ago•GHSA-3GJW-F78C-VVPW
7.5

GHSA-3GJW-F78C-VVPW: Denial of Service via Unhandled Out-of-Bounds Indexing Panic in tokio-postgres

An issue was discovered in the tokio-postgres library for Rust prior to version 0.7.18. A trust assumption mismatch between the PostgreSQL protocol messages sent by a server and how they are parsed and indexed by the client-side library allows a rogue or compromised database server to trigger a Denial of Service (DoS) crash via an unhandled out-of-bounds slice indexing panic.

Alon Barad
Alon Barad
5 views•6 min read
•about 18 hours ago•CVE-2026-14669
8.8

CVE-2026-14669: PostgreSQL to_char() Timezone Abbreviation Heap-Based Buffer Overflow

CVE-2026-14669 is a critical heap-based buffer overflow vulnerability in PostgreSQL's date/time formatting function to_char(timestamptz). The flaw arises from unsafe copying of user-controlled timezone abbreviations into a fixed-size internal buffer. An authenticated database user can trigger this issue by setting a long POSIX timezone abbreviation containing custom formatting, allowing them to overwrite adjacent heap structures and hijack execution control to achieve remote code execution (RCE) with the privileges of the 'postgres' operating system user.

Alon Barad
Alon Barad
13 views•6 min read
•2 days ago•CVE-2026-63462
7.5

CVE-2026-63462: Unauthenticated Stack Overflow Denial of Service in Unleash Server

An unauthenticated remote denial of service vulnerability exists in the Unleash feature management platform. By submitting a crafted JSON payload containing deeply nested structures to an OpenAPI-validated endpoint, an attacker can trigger uncontrolled recursion within the error formatting module. This leads to a call-stack exhaustion (RangeError: Maximum call stack size exceeded) inside the Node.js runtime, causing the service to crash immediately without recovery.

Alon Barad
Alon Barad
11 views•6 min read
•3 days ago•CVE-2026-63004
5.5

CVE-2026-63004: Server-Side Request Forgery in Unleash Addon and Integration Subsystem

CVE-2026-63004 is a server-side request forgery (SSRF) vulnerability in the Unleash feature management platform. Authenticated administrators with CREATE_ADDON or UPDATE_ADDON privileges can exploit this vulnerability to initiate requests to loopback addresses, private networks, and cloud metadata endpoints, potentially leading to information disclosure and credential extraction.

Amit Schendel
Amit Schendel
9 views•8 min read
•3 days ago•CVE-2026-63466
4.1

CVE-2026-63466: Process-Wide Security Degradation via Global Module Mutation in Unleash

Prior to version 8.0.3, Unleash's Markdown event formatter directly mutated the global template-escaping function of the shared mustache Node.js module, resulting in a process-wide security degradation where HTML/Markdown escaping was permanently disabled for the application lifetime.

Alon Barad
Alon Barad
3 views•6 min read