CVE-2026-80231: Verified Reproduction
CVE-2026-80231: curl: native CA store flag not part of connection reuse matching, wrong trust store may authenticate reused TLS connections
CVE-2026-80231 is verified against curl/libcurl · github. Affected versions: curl 7.71.0 through 8.21.0 inclusive. This low reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00346.
What Is CVE-2026-80231?
CVE-2026-80231 is a low-severity vulnerability affecting curl/libcurl curl 7.71.0 through 8.21.0 inclusive.. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00346).
CVE-2026-80231 Severity
CVE-2026-80231 is rated low severity.
Low — limited impact or hard to exploit. Address in the normal cycle.
Affected curl/libcurl Versions
curl/libcurl · github versions curl 7.71.0 through 8.21.0 inclusive. are affected.
How to Reproduce CVE-2026-80231
pruva-verify REPRO-2026-00346 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00346/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-80231
- reached the target end-to-end
- full exploit chain demonstrated
- high confidence
- the upstream fix blocks the same trigger
HTTPS origin certificate accepted only through native system trust, followed by a request whose explicit custom CA policy should reject it
- curl_multi API sequential same-origin transfers
- connection cache match
- reused TLS connection despite different effective native_ca_store policy
How the agent worked
Root Cause and Exploit Chain for CVE-2026-80231
CVE-2026-80231 is a libcurl TLS connection-reuse matching flaw. Before the fix, the effective native_ca_store setting was stored outside ssl_primary_config, so match_ssl_primary_config() did not include it when deciding whether a pooled connection was compatible with a later transfer. A same-origin request configured with explicit custom CA material could therefore reuse an HTTPS connection established using native system trust, even though opening a fresh connection under that later policy correctly rejected the server certificate.
- Affected package/component: curl/libcurl virtual TLS configuration and connection cache.
- Affected versions: curl 7.71.0 through 8.21.0, introduced by commit
148534db57dda611cf8516e92e4d6e35fc1e5074and fixed by commit7be1e70cb6bcd83e130ecfe8cb91b6a7dcdeff42in curl 8.22.0. - Risk and consequence: A caller's later trust-store restriction is not enforced when an origin connection created under native CA trust is reused. A certificate that the later transfer's configured CA policy does not authorize is accepted through stale pooled TLS state. This is an authentication/authorization-policy bypass (CWE-488) rated Low upstream because it requires connection reuse and platform/backend native-store support.
Impact Parity
- Disclosed/claimed maximum impact: Authorization/authentication-policy bypass through reuse of a TLS connection created under a different native CA-store setting.
- Reproduced impact from this run: The vulnerable parent sent an HTTPS request successfully over a native-trusted pooled connection after the second easy handle explicitly selected an empty CA file. The same explicit policy on a fresh cache failed certificate verification (
CURLE_PEER_FAILED_VERIFICATION, code 60). The fixed commit did not reuse that connection and failed the second request closed. - Parity:
full. - Not demonstrated: No code execution, memory corruption, or privilege escalation was claimed or attempted.
Root Cause
Curl_ssl_easy_config_complete() determines whether native CA trust is active from CURLOPT_SSL_OPTIONS, native-CA build defaults, and whether the application explicitly supplied CA material. In the vulnerable parent, that result was written to ssl_config_data.native_ca_store. Connection pooling, however, calls Curl_ssl_conn_config_match(), which compares only fields in ssl_primary_config through match_ssl_primary_config(). Thus, two easy handles could have equal compared values such as ssl_options and final CAfile, while differing in the effective native CA decision. The pooled connection carried the first handle's already completed trust decision into the second transfer.
The reproducer creates exactly this state without mocking libcurl: both handles resolve to the same empty CA-file path and use ssl_options=0; the first gets the path as a build default, which leaves implicit native CA active, while the second explicitly sets the same path, marking CA material custom and disabling implicit native CA. The vulnerable matcher treats these configurations as equal. Fix commit 7be1e70cb6bc moves native_ca_store into ssl_primary_config, clones it into connections, compares it in match_ssl_primary_config(), and updates the OpenSSL, GnuTLS, rustls, and wolfSSL backends to consult connection-primary state.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.shfrom any directory (the script derives or honorsPRUVA_ROOT). - The script uses the prepared project cache when available, resolves the fixed commit and its exact parent, verifies the patch hunk is absent/present as expected, and builds both commits with shared libcurl, GnuTLS, and
CURL_CA_NATIVE=ON. - It creates a localhost HTTPS certificate trusted only through GnuTLS system/native trust, starts a keep-alive HTTPS origin, compiles the real libcurl multi-API harness, and executes two vulnerable plus two fixed attempts.
- Expected result: the script exits 0 and prints
CONFIRMED. Vulnerable logs containORACLE=VULNERABLE_WRONG_TRUST_REUSE; fixed logs containORACLE=FIXED_POLICY_ISOLATION.
Evidence
- Runtime contract:
bundle/repro/runtime_manifest.jsonbinds target commit7ea37abc6ac0120ba5f6d94be8d196f7cf1506bb, tested build identities, and SHA-256 digests for all proof artifacts. - Vulnerable observations:
bundle/repro/vulnerable-attempt-1.logandvulnerable-attempt-2.logshow:native-default-prime code=0 ... new_connects=1 http=200Reusing existing https: connection with host localhostcustom-same-path-shared-cache code=0 ... new_connects=0 http=200- Fresh control:
code=60 ... new_connects=1 http=0 ORACLE=VULNERABLE_WRONG_TRUST_REUSE
- Fixed negative controls:
bundle/repro/fixed-attempt-1.logandfixed-attempt-2.logshow the shared-cache custom policy creates a new connection and fails with code 60, followed byORACLE=FIXED_POLICY_ISOLATION. - Target/linker identity:
bundle/repro/build-identity-vulnerable.txtandbuild-identity-fixed.txtrecord commits, curl/GnuTLS versions,lddresolution to each intended builtlibcurl.so.4, and binary SHA-256 values. - Origin evidence:
bundle/repro/server.logrecords readiness and the six successful HTTP requests expected across two vulnerable reuse attempts plus two fixed priming requests. - Diagnostics:
bundle/logs/reproduction_steps.log,build-vulnerable*.log, andbuild-fixed*.log. - Environment: Linux x86_64, GnuTLS 3.8.12, libcurl 8.22.0-DEV source at the exact vulnerable parent/fixed commits. Although the upstream advisory states deployed exposure exists on Windows/macOS,
CURL_CA_NATIVE=ONwith GnuTLS exposes the same real libcurl native-store decision and connection matcher on this Linux worker, allowing direct runtime validation of the root cause and fixed divergence.
Recommendations / Next Steps
- Upgrade to curl 8.22.0 or later, or apply commit
7be1e70cb6bc. - As an interim mitigation, use
CURLOPT_FORBID_REUSEfor transfers using native CA trust, as recommended by the upstream advisory. - Keep every certificate-verification option that affects connection compatibility in the primary connection configuration and include it in clone, session/cache, and reuse comparisons.
- Add upstream regression coverage equivalent to this proof for each native-CA-capable TLS backend, plus Windows and macOS product builds.
Additional Notes
- The final reproduction script passed twice consecutively. Each invocation itself ran two vulnerable and two fixed attempts, yielding four fresh observations per role across final verification.
- The script restores the host trust store during cleanup and generates its server certificate and server helper at runtime.
- The only non-generated bundle dependency is
bundle/repro/native_ca_reuse_harness.c; all other runtime helpers, keys, certificates, builds, and logs are created by the script. - The proof uses a real libcurl library API boundary and a real TLS/HTTP exchange, not a parser reimplementation, mock result, sanitizer, or source-only assertion.
CVE-2026-80231 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
# Root Cause Analysis: CVE-2026-80231 ## Summary CVE-2026-80231 is a libcurl TLS connection-reuse matching flaw. Before the fix, `CURLSSLOPT_NATIVE_CA` was stored outside `ssl_primary_config`, so `match_ssl_primary_config()` did not treat the native-CA-store choice as part of a pooled connection's identity. Sequential easy handles sharing a connection cache could therefore reuse an already authenticated HTTPS connection despite requesting a different native CA-store policy. ## Impact - **Affected package/component:** curl/libcurl virtual TLS configuration and connection cache. - **Affected versions:** Introduced by commit `148534db57dd` (curl 7.71.0) and fixed by commit `7be1e70cb6bc` for curl 8.22.0. - **Risk and consequence:** On platforms/backends where native CA-store selection changes certificate validation, a connection authenticated under one trust-store policy may be reused by a handle requesting another policy. This can bypass the caller's intended peer-authentication policy. The ticket rates severity as low because exploitation depends on platform TLS behavior, shared connection reuse, and sequential requests to the same origin. ## Impact Parity - **Disclosed/claime… [truncated]
Artifacts and Evidence for CVE-2026-80231
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-80231
FAQ: CVE-2026-80231
Is CVE-2026-80231 exploitable?
How severe is CVE-2026-80231?
What type of vulnerability is CVE-2026-80231?
Which versions of curl/libcurl are affected by CVE-2026-80231?
How can I reproduce CVE-2026-80231?
Is the CVE-2026-80231 reproduction verified?
References for CVE-2026-80231
Authoritative sources for CVE-2026-80231 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.