| Version | Supported |
|---|---|
| 4.5.x | [OK] Active |
| 4.0.x | [!] Critical fixes only (upgrade to 4.1.x recommended) |
| 3.20.x | [!] Critical fixes only |
| < 3.20 | [FAIL] Unsupported |
Security fixes apply to the latest release on the main branch.
Do NOT open a public issue for suspected vulnerabilities.
Report privately via one of:
-
GitHub Security Advisories (preferred and primary channel): Create advisory
GitHub Security Advisories keep the report confidential until a fix is released and are the recommended path for coordinated disclosure.
We will acknowledge within 72 hours and provide a fix timeline.
- Incorrect field or scalar arithmetic
- Point operation errors (addition, doubling, scalar multiplication)
- ECDSA / Schnorr signature forgery or invalid verification
- MuSig2, FROST, Adaptor Signature, or Pedersen Commitment correctness failures
- SHA-256 / tagged-hash collisions or incorrect output
- Determinism violations (RFC 6979 nonce generation)
- Constant-time violations (timing side channels in
ct::namespace) - Memory safety issues (buffer overflows, use-after-free)
- GPU kernel correctness issues (CUDA, ROCm, OpenCL, Metal)
- BIP-32 / BIP-44 HD derivation errors
- Coin-specific address generation errors (28-coin dispatch)
- Undefined behavior affecting cryptographic correctness
No external third-party audit has been completed. The codebase has undergone intensive internal self-audit and multiple multi-agent AI review passes, but has not been reviewed by a paid external cryptographic auditing firm. Treat it accordingly when considering production use in high-value systems.
For details on the reproducible self-audit system (CAAS — Continuous Automated Assurance System)
that provides structured, replayable security evidence, see
docs/CAAS_REVIEWER_QUICKSTART.md.
The primary security posture is an open, reproducible self-audit program that any outside reviewer can rerun. The project philosophy is to strengthen assurance through internal audit on every build and every commit. The project is designed to make external review as efficient as possible: reproducible artifacts, graph-backed code navigation, structured traceability, and CI-backed verification that any reviewer can replay independently.
Open self-audit and reproducible review
The project prioritizes transparent audit artifacts, reproducible commands, public traceability documents, and CI-backed verification that other engineers can independently rerun as part of the CAAS model. The model is deliberately Bitcoin-style: don't trust, verify. That includes graph-backed code navigation, continuously expanding adversarial tests, and frequent external-style review passes that feed new edge cases back into the reproducible audit framework. External review is welcome, and the repository is prepared so outside auditors can step in at any time. Meanwhile, the internal goal is to keep assurance work active, continuous, and verifiable in the open on every build and every commit.
Claim references for this section: CPU CT signing discipline A-001, exploit-audit surface A-005, graph-assisted review A-006, open self-audit transparency A-007, and ROCm/HIP status discipline A-008 in docs/ASSURANCE_LEDGER.md.
For auditors and security researchers, the following documents are available:
| Document | Purpose |
|---|---|
| AUDIT_GUIDE.md | Start here -- Auditor navigation, checklist, reproduction commands |
| AUDIT_REPORT.md | Internal audit report (v4.5.0 baseline; test suite significantly restructured since -- see below) |
| THREAT_MODEL.md | Layer-by-layer risk + attack surface analysis |
| docs/ARCHITECTURE.md | Technical architecture for auditors |
| docs/CT_VERIFICATION.md | Constant-time methodology, dudect, known limitations |
| docs/TEST_MATRIX.md | Function -> test coverage map with gap analysis |
The following automated security measures are in place:
- Gate workflow -- block-based PR/push gate with impact detection, fast CAAS checks, selected profile gates, and final verdict
- Release CAAS gate -- release tags must pass CAAS evidence checks before build/package fan-out
- CodeQL / Clang-Tidy / SonarCloud / Scorecard -- available as manual deep-assurance workflows
- ASan / UBSan / TSan / Valgrind -- available as manual or release-policy deep-assurance workflows
- Artifact Attestation -- SLSA provenance for all release artifacts
- SHA-256 Checksums --
SHA256SUMS.txtships with every release - Dependabot -- automated dependency updates for all ecosystems
- Dependency Review -- PR-level vulnerable dependency scanning
- libFuzzer harnesses -- continuous fuzz testing of field/scalar/point layers
- Docker SHA-pinned images -- reproducible builds with digest-pinned base images
- dudect timing analysis -- Welch t-test side-channel detection (1300+ line test suite)
- Native ARM64 dudect -- Apple Silicon (M1) smoke + full statistical analysis on macos-14 runners
- ct-verif LLVM pass -- deterministic compile-time constant-time verification of CT modules
- Internal audit suite -- active CTest targets in the current validation surface, including fuzz parsers, differential tests, fault injection, CT equivalence, cross-platform KAT, Wycheproof ECDSA/ECDH, independent reference linkage, and a unified audit runner spanning a non-exploit module set plus an exploit-PoC module set across 9 sections (exact counts via
python3 ci/sync_module_count.py). - Valgrind CT taint analysis -- MAKE_MEM_UNDEFINED + --track-origins secret-dependent branch detection
- MuSig2/FROST dudect -- protocol-level timing analysis (partial_sign, frost_sign, Lagrange)
- SARIF audit output --
--sarifflag for GitHub Code Scanning integration - Perf regression gate -- per-push/PR benchmark gate, fails on material regressions (>50% slower on the shared-runner threshold used in CI)
- Expand external reproducibility packs for outside reviewers (one-command audit replay, artifact bundles, and reviewer checklists)
- Funded bug bounty program -- seeking sponsors to offer financial rewards for vulnerability reports
- [~] Formal verification of field/scalar arithmetic (Fiat-Crypto / Cryptol) — Cryptol spec files present in
formal/cryptol/; runs as advisory CI gate (skips when Cryptol not installed; not a hard blocking gate) - ct-verif LLVM pass integration for compile-time CT verification (
.github/workflows/ct-verif.yml) - Native ARM64 / Apple Silicon dudect CI -- macos-14 M1 runner, smoke + full (
.github/workflows/ct-arm64.yml) - Multi-uarch dudect campaign -- x86-64 native + RISC-V via QEMU + ARM64 cross-compile
- CT buffer erasure -- volatile function-pointer trick +
explicit_bzero/std::atomic_signal_fencein signing paths - value_barrier on CT mask derivation
- CT branchless low-S normalization (
ct_normalize_low_s) -- eliminates timing leak in ECDSA signing - CT branchless parity handling in Schnorr signing (
scalar_cneg+bool_to_mask) - Complete secret zeroization in CT Schnorr sign (d_bytes, t_hash, rand_hash, k_prime, k)
- Independent reference linkage test (schoolbook oracle cross-check, 6085 checks) + Fiat-Crypto golden vectors
- Google Wycheproof ECDSA (89 vectors) + ECDH (36 vectors) integration
- Valgrind CT taint CI -- secret-dependent branch detection (
.github/workflows/valgrind-ct.yml) - MuSig2/FROST protocol-level dudect -- timing tests for partial_sign, frost_sign, Lagrange
- SARIF output from audit runner --
--sarifCLI flag + GitHub Code Scanning upload - Performance regression gate -- per-commit 120% threshold (
.github/workflows/bench-regression.yml) - FROST / MuSig2 reference test vectors from BIP-327/RFC-9591 implementations
- Cross-ABI / FFI hostile-caller and thread-stress validation across the public C ABI
For production cryptographic systems, verify the exact build, feature profile, and CAAS evidence bundle you intend to rely on.
See THREAT_MODEL.md for a layer-by-layer risk assessment.
| Component | Status | Notes |
|---|---|---|
| Field / Scalar arithmetic | Stable | Extensive KAT + fuzz coverage |
| Point operations (add, dbl, mul) | Stable | Deterministic selftest (smoke/ci/stress) |
| ECDSA (RFC 6979) | Stable | Deterministic nonces, input validation |
| Schnorr (BIP-340) | Stable | Tagged hashing, input validation |
Constant-time layer (ct::) |
Stable | No secret-dependent branches; ~2-3x penalty vs FAST path |
| Batch inverse / multi-scalar | Stable | Sweep-tested up to 8192 elements |
| GPU backends (CUDA, OpenCL, Metal; ROCm/HIP build path) | Beta | CT signing paths added in v4.0 (CUDA/OpenCL/Metal) |
| MuSig2 / FROST / Adaptor | Experimental | API may change |
| Pedersen Commitments | Experimental | API may change |
| Taproot (BIP-341) | Experimental | API may change |
| HD Derivation (BIP-32/44) | Experimental | API may change |
| Multi-coin address dispatch | Experimental | API may change |
The constant-time layer (ct:: namespace) provides:
ct::field_mul,ct::field_inv-- timing-safe field arithmeticct::scalar_mul-- timing-safe scalar multiplicationct::point_add_complete,ct::point_dbl-- complete addition formulas
The CT layer uses no secret-dependent branches or memory access patterns. It carries a performance penalty relative to the optimized (variable-time) path — see docs/bench_unified_2026-05-21_gcc14_x86-64.json for current GCC 14.2.0 measurements (prior GCC 13 figures of 2.17×/2.68× are unverified against the current implementation and have been retired).
Important: The default (non-CT) operations prioritize performance and are NOT constant-time. Use the ct:: variants when processing secret keys or nonces.
The following functions are documented exceptions where a fast:: code path was historically used in a secret-key context. Each has been assigned a tracking ID; the fix status is noted.
| ID | Function | Issue | Status |
|---|---|---|---|
| Q-07 | ::ecdsa_sign_recoverable() in recovery.cpp |
Called by bitcoin_sign_message() and the libsecp256k1 shim -- uses fast::scalar_mul(k) and fast::scalar_inverse(k) on the secret nonce, leaking timing information about k. Affects Sparrow Wallet, ECIES, Ethereum personal_sign, and any caller using the recovery-ID signing path. |
Fixed -- bitcoin_sign_message() and secp256k1_ecdsa_sign_recoverable() now call ct::ecdsa_sign_recoverable() (added in ct_sign.cpp), which uses ct::generator_mul() for R=k*G and ct::scalar_inverse() for k^{-1}. The variable-time ::ecdsa_sign_recoverable() remains available for public-data contexts (address search, batch verification) but must not be called with a secret key. |
Rule: any function that accepts or derives a private key or secret nonce -- including message-signing wrappers -- must route through ct::. Filing a new exception requires an explicit SECURITY.md entry before the code ships.
- ECDSA: Deterministic nonces via RFC 6979 (no random nonce generation needed)
- Schnorr: BIP-340 compliant with tagged hashing
- Both signature schemes include validation of inputs (point-on-curve, scalar range checks)
- No dynamic allocation in hot paths
- Library-side secret erasure:
ct::schnorr_signandct::ecdsa_signautomatically erase all intermediate nonces, scalar buffers, hash intermediates, and serialized key material viasecure_erase(volatile function-pointer trick +explicit_bzeroon glibc/BSD,std::atomic_signal_fencecompiler barrier). The compiler cannot elide this erasure. value_barrierapplied to CT mask derivations to prevent compiler speculation- Fixed-size POD types used throughout (no hidden copies)
- Callers should still erase their own copies of private keys after use
libFuzzer harnesses cover the core arithmetic layers:
| Target | File | Operations |
|---|---|---|
| Field | src/cpu/fuzz/fuzz_field.cpp |
add/sub round-trip, mul identity, square, inverse |
| Scalar | src/cpu/fuzz/fuzz_scalar.cpp |
add/sub, mul identity, distributive law |
| Point | src/cpu/fuzz/fuzz_point.cpp |
on-curve check, negate, compress round-trip, dbl vs add |
# Example: run field fuzzer
clang++ -fsanitize=fuzzer,address -O2 -std=c++20 \
-I src/cpu/include src/cpu/fuzz/fuzz_field.cpp src/cpu/src/field.cpp src/cpu/src/field_asm.cpp \
-o fuzz_field
./fuzz_field -max_len=64 -runs=10000000UltrafastSecp256k1 provides:
- Finite field arithmetic (𝔽ₚ for secp256k1 prime)
- Scalar arithmetic (mod n, curve order)
- Elliptic curve point operations (add, double, scalar multiply, multi-scalar)
- Batch inverse (Montgomery trick)
- ECDSA signatures (RFC 6979)
- Schnorr signatures (BIP-340)
- MuSig2 / FROST / Adaptor Signatures / Pedersen Commitments
- Taproot (BIP-341/342)
- HD key derivation (BIP-32/44)
- 27-coin address generation dispatch
- SHA-256 / tagged hashing
- GPU-accelerated batch operations (CUDA, ROCm, OpenCL, Metal)
- Constant-time layer (
ct::namespace)
Out of scope: Key storage, wallet software, network protocols, consensus rules, and application-layer cryptographic protocols. Security responsibility for higher-level integrations remains with the integrating application.
As of v4.0, the public C ABI (ufsecp_* functions) and the ct:: signing namespace are stable. Breaking changes to stable layers will follow semantic versioning (major version bump).
Layers marked "Stable" in the Production Readiness table above have guaranteed backwards compatibility. Layers marked "Experimental" may change in any minor release.
For detailed stability classifications, see:
- docs/adoption/API_STABILITY.md -- Tiered header classification (Stable / Provisional / Experimental / Internal)
- docs/ABI_VERSIONING.md -- MAJOR.MINOR.PATCH + ABI version
- docs/DEPRECATION_POLICY.md -- 2 minor release deprecation cycle
- docs/LTS_POLICY.md -- 12-month LTS, SemVer 2.0.0
We follow a coordinated disclosure process with severity-tiered SLAs.
A machine-readable contact record per RFC 9116 is published at
.well-known/security.txt.
| Phase | Timeline | Action |
|---|---|---|
| Acknowledgment | <= 72 hours | Confirm receipt, assign tracking ID |
| Assessment | <= 7 days | Severity classification (CVSS 3.1) |
| Severity | Fix-by | Advisory-by | Notes |
|---|---|---|---|
| Critical (CVSS >= 9.0) | <= 7 days | <= 14 days | Private key recovery, signature forgery, parser RCE |
| High (CVSS 7.0-8.9) | <= 30 days | <= 60 days | CT violation in ct:: namespace, nonce bias, ABI memory safety |
| Medium (CVSS 4.0-6.9) | <= 60 days | <= 90 days | DoS, unexpected abort, secret-bit leakage that does not yield key |
| Low (CVSS 0.1-3.9) | Best effort | Bundled | Non-security correctness, edge-case handling |
These SLAs are commitments, not best-effort goals. If we miss an
SLA we file a public note in docs/AUDIT_CHANGELOG.md explaining
why; this is verified by the CAAS sub-gate
ci/audit_gate.py --disclosure-sla (planned).
| CVSS | Example |
|---|---|
| Critical (9.0+) | Private key recovery, signature forgery |
| High (7.0-8.9) | CT violation in ct:: namespace, nonce bias |
| Medium (4.0-6.9) | Denial of service, unexpected panic/abort |
| Low (0.1-3.9) | Non-security correctness issues, edge-case handling |
Reporters are credited in the changelog and the GitHub Security Advisory (unless they request anonymity). We do not require embargoes that are longer than 90 days; if 90 days pass without a fix, the reporter is free to disclose.
For detailed eligibility criteria, scope, and reward guidelines, see docs/BUG_BOUNTY.md.
Summary of scope:
- In scope: Field/scalar/point arithmetic, ECDSA/Schnorr/MuSig2/FROST correctness, constant-time violations, memory safety, GPU kernel correctness
- Out of scope: Performance issues, documentation errors, features not yet marked "Stable"
We appreciate responsible disclosure. Contributors who report valid security issues will be credited in the changelog (unless they prefer anonymity).
- Damir — GHSA-c7q2-gv3g-rgxm: ECDSA adaptor pre-signature soundness (missing DLEQ binding of
rto the adaptor point), reported with a working PoC and fixed insrc/cpu/src/adaptor.cpp(DLEQ-bound construction). CVE request pending.
UltrafastSecp256k1 v4.5.0 -- Security Policy