# REPRO-2026-00089: pyca/cryptography SECT curve public key parsing lacks subgroup validation, enabling small-subgroup attacks that leak ECDH private key bits and allow ECDSA signature forgery. ## Summary Status: published Severity: high Type: security Confidence: Unknown ## Identifiers REPRO ID: REPRO-2026-00089 GHSA: GHSA-R6PH-V2QM-Q3C2 CVE: CVE-2026-26007 ## Package Name: Unknown Ecosystem: Unknown Affected: Unknown Fixed: Unknown ## Root Cause # Root Cause Analysis Report ## Summary pyca/cryptography accepts SECT curve public keys without verifying subgroup membership. For curves with cofactor > 1 (e.g., SECT163K1), a malicious point of small order can be loaded and used in ECDH, causing the shared secret to depend only on the victim’s private key modulo the small subgroup order. This enables leakage of private key bits and breaks protocol security. ## Impact - **Package/component affected:** pyca/cryptography EC public key parsing and construction paths (EllipticCurvePublicNumbers.public_key, load_der_public_key, load_pem_public_key). - **Affected versions:** <= 46.0.4 (per ticket). - **Risk level and consequences:** High. Small-subgroup points allow ECDH key leakage (private key mod small subgroup order) and can lead to ECDSA forgery in small subgroups. ## Root Cause The EC public key parsing/building logic relies on OpenSSL EC point construction without enforcing subgroup membership checks for binary SECT curves with nontrivial cofactor. In the Rust key parsing path (`cryptography/src/rust/cryptography-key-parsing/src/spki.rs`), points are accepted via `EcPoint::from_bytes` and `EcKey::from_public_key` without an explicit subgroup validation step. Similarly, `EllipticCurvePublicNumbers.public_key()` constructs a public key without verifying that the point is in the prime-order subgroup. This allows small-order points (e.g., order-2 point (0,1) on SECT163K1) to be accepted as valid public keys. ## Reproduction Steps 1. Run `repro/reproduction_steps.sh`. 2. The script installs `cryptography==46.0.4`, constructs a small-subgroup SECT163K1 public key at point (0,1), and performs ECDH with private keys 1–4. 3. Expected evidence: the point is accepted; odd private keys succeed with a constant shared secret, while even private keys fail, revealing private key parity (mod 2). ## Evidence - Log file: `logs/repro_output.txt` - Key excerpts: - "accepted small-subgroup point (0,1) on SECT163K1" - `d=1 status=ok ...` and `d=2 status=err ...` demonstrating parity leakage. - Environment: Python 3 with `cryptography==46.0.4` installed by the script. ## Recommendations / Next Steps - Add explicit subgroup membership checks for SECT curves with cofactor > 1 when constructing or loading public keys. - Reject points not in the prime-order subgroup or perform cofactor multiplication validation. - Upgrade to a fixed cryptography release once available and add regression tests for small-subgroup points. ## Additional Notes - Idempotent: running `repro/reproduction_steps.sh` repeatedly yields the same acceptance/leakage pattern. - Limitation: demonstration focuses on SECT163K1 order-2 subgroup; other SECT curves with higher cofactors are also affected. ## Reproduction Details Reproduced: 2026-02-15T08:07:18.562Z Duration: 392 seconds Tool calls: 68 Turns: Unknown Handoffs: 2 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00089 pruva-verify GHSA-R6PH-V2QM-Q3C2 pruva-verify CVE-2026-26007 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00089&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00089/artifacts/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - GitHub Advisory: https://github.com/advisories/GHSA-R6PH-V2QM-Q3C2 - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-26007 - Source: https://github.com/advisories/GHSA-R6PH-V2QM-Q3C2 ## Artifacts - repro/rca_report.md (analysis, 2758 bytes) - repro/reproduction_steps.sh (reproduction_script, 1594 bytes) - vuln_variant/rca_report.md (analysis, 4511 bytes) - vuln_variant/reproduction_steps.sh (reproduction_script, 3122 bytes) - bundle/ticket.md (ticket, 2192 bytes) - logs/repro_output.txt (other, 330 bytes) - logs/pip_install.txt (other, 384 bytes) - vuln_variant/patch_analysis.md (documentation, 1359 bytes) - logs/variant_attempts.txt (other, 1037 bytes) - logs/variant_pip_install.txt (other, 384 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00089 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00089/artifacts/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00089 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev