Skip to content

CVE-2026-82208: Verified Reproduction

CVE-2026-82208: curl: wolfSSL CA-cache hit causes x509 store setup rerun that overrides user certificate verification callback

CVE-2026-82208 is verified against curl/curl · github. Affected versions: curl 8.9.1 through 8.21.0 inclusive. This low reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00368.

REPRO-2026-00368 curl/curl · github Sep 24, 2026 CVE entry .txt
Severity
LOW
Confidence
HIGH
Reproduced in
25m 40s
Tool calls
237
Spend
$29.09
01 · Overview

What Is CVE-2026-82208?

CVE-2026-82208 is a low-severity vulnerability affecting curl/curl curl 8.9.1 through 8.21.0 inclusive.. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00368).

02 · Severity & CVSS

CVE-2026-82208 Severity

CVE-2026-82208 is rated low severity.

LOW threat level
Weakness CWE-295: Improper Certificate Validation. — Improper Certificate Validation

Low — limited impact or hard to exploit. Address in the normal cycle.

03 · Affected Versions

Affected curl/curl Versions

curl/curl · github versions curl 8.9.1 through 8.21.0 inclusive. are affected.

How to Reproduce CVE-2026-82208

$ pruva-verify REPRO-2026-00368
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00368/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-82208

Authorization bypass — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

An HTTPS peer certificate trusted by the cached CA store but rejected after the CURLOPT_SSL_CTX_FUNCTION callback replaces the trust store with an empty store

Attack chain
  1. curl_multi API
  2. first CAfile transfer populates wolfSSL CA cache
  3. fresh second transfer invokes CURLOPT_SSL_CTX_FUNCTION
  4. vulnerable Curl_wssl_setup_x509_store rerun reinstalls cached store
How the agent worked 446 events · 237 tool calls · 25 min
25 minDuration
237Tool calls
52Reasoning steps
446Events
18Dead-ends
Agent activity over 25 min
Policy
1
Support
39
Repro
224
Judge
28
Variant
149
Verify
1
0:0025:20

Root Cause and Exploit Chain for CVE-2026-82208

Versions: curl 8.9.1 through 8.21.0 inclusive. Versions before 8.9.1 and curl 8.22.0 or later are not affected.

CVE-2026-82208 is a certificate-policy bypass in libcurl's wolfSSL TLS backend. When CA caching is enabled, a cache-hit connection can leave wssl->x509_store_setup false. libcurl calls Curl_wssl_setup_x509_store() before an application's CURLOPT_SSL_CTX_FUNCTION callback, the callback replaces the trust store with stricter application policy, and then libcurl calls setup again during the handshake. The vulnerable second call silently reinstalls the cached CA store, overriding the callback's policy. Current-run testing reproduced the bypass twice against the vulnerable fixed-commit parent and showed the fixed commit rejecting the same second transfer twice.

  • Package/component affected: curl/libcurl, specifically the wolfSSL TLS backend when CA caching and CURLOPT_SSL_CTX_FUNCTION trust-store customization are used.
  • Affected versions: curl 8.9.1 through 8.21.0 inclusive. Versions before 8.9.1 and curl 8.22.0 or later are not affected.
  • Tested vulnerable commit: f8df560ed9faa2ff3d6198b50f55eaf0315fcb39, the direct parent of the fixed commit.
  • Tested fixed commit: ed0338befd1d865a8ea1fbaa90013a096dedd07a.
  • Risk level and consequences: Upstream rates this Low severity (CWE-295). Under the required application configuration, an HTTPS peer certificate accepted by the cached CA store can be accepted even though application-installed certificate policy rejects it, undermining authentication and authorization decisions based on that policy. The curl command-line tool is not affected because this requires libcurl callback use.

Impact Parity

  • Disclosed/claimed maximum impact: Certificate-policy/authorization bypass (authz_bypass).
  • Reproduced impact from this run: Full policy bypass. On each vulnerable run, the application callback installed an empty wolfSSL trust store, yet the second TLS handshake succeeded and received HTTP 200 from the peer. The fixed commit failed the same transfer with CURLE_SSL_CACERT_BADFILE (77) after reporting that the CA signer was unavailable.
  • Parity: full.
  • Not demonstrated: No code execution, memory corruption, or effect beyond bypassing the configured certificate trust policy was claimed or tested.

Root Cause

The CA cache is held on the libcurl multi handle. In the vulnerable implementation, the line that marks setup complete—wssl->x509_store_setup = TRUE—is inside wssl_populate_x509_store(). A cache miss populates a new store and reaches that assignment. A cache hit, however, takes the cached_store branch in Curl_wssl_setup_x509_store() and returns without calling wssl_populate_x509_store(), so the completion flag remains false.

During a new wolfSSL connection, libcurl first checks this flag and installs the cached store before calling the application's CURLOPT_SSL_CTX_FUNCTION callback. The callback can replace the trust store to enforce stricter policy. Later in the handshake, libcurl checks the still-false flag again, invokes Curl_wssl_setup_x509_store() a second time, and restores the cached store. The callback did execute, but its trust decision state no longer controls certificate validation.

The fix moves wssl->x509_store_setup = TRUE to the beginning of Curl_wssl_setup_x509_store(), ensuring every path—including a cache hit—is marked complete and preventing the post-callback rerun:

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh with PRUVA_ROOT optionally pointing to the bundle directory.
  2. The script reads bundle/project_cache_context.json, uses /pruva/project-cache/repo when prepared, fetches fixed commit ed0338befd1d865a8ea1fbaa90013a096dedd07a, resolves its parent as the vulnerable checkout, and verifies the patch is absent/present in the expected function preamble.
  3. It builds pinned wolfSSL 5.8.4 commit 59f4fa568615396fbf381b073b220d1e8d61e4c2 and static vulnerable/fixed libcurl builds with no default CA path. This makes the explicit CAfile the sole trust source and satisfies the wolfSSL CA-cache criteria.
  4. It generates a local CA/server certificate and starts a real local HTTPS peer.
  5. For each role, a C application performs one CAfile-authenticated transfer to populate the multi handle's CA cache, then a fresh second transfer with CURLOPT_SSL_CTX_FUNCTION. The callback replaces the wolfSSL X.509 store with an empty store, which must reject the server certificate if preserved.
  6. The script runs two vulnerable and two fixed attempts. It requires vulnerable HTTP 200 acceptance, fixed certificate rejection, and exactly six HTTP requests reaching the peer (four vulnerable requests plus two fixed cache-priming requests).
  7. It writes bundle/repro/runtime_manifest.json with immutable target identity and proof-artifact SHA-256 values.

Expected terminal output is:

CVE-2026-82208 CONFIRMED: vulnerable CA-cache hit overrides callback-selected trust store; fixed commit fails closed.

Evidence

  • Vulnerable attempts:
    • bundle/repro/vulnerable-attempt-1.log
    • bundle/repro/vulnerable-attempt-2.log
  • Fixed negative controls:
    • bundle/repro/fixed-attempt-1.log
    • bundle/repro/fixed-attempt-2.log
  • Real HTTPS peer transcript: bundle/repro/https-peer.log
  • Exact source/dependency identity: bundle/repro/target-identity.log
  • Machine-readable evidence binding: bundle/repro/runtime_manifest.json
  • Build/session diagnostics: bundle/logs/reproduction_steps.log and bundle/logs/fix.patch

Key vulnerable excerpt (present in both vulnerable logs):

CALLBACK_EMPTY_STORE_INSTALLED
* SSL connection using TLSv1.3 / TLS13-AES256-GCM-SHA384
< HTTP/1.1 200 OK
SECOND_RESULT code=0 name=No error http=200
VULNERABILITY_CONFIRMED cached_CA_overrode_callback_policy

Key fixed excerpt (present in both fixed logs):

CALLBACK_EMPTY_STORE_INSTALLED
*  CA signer not available for verification
SECOND_RESULT code=77 name=Problem with the SSL CA cert (path? access rights?) http=0
FIXED_NEGATIVE_CONTROL callback_policy_enforced

The final runtime manifest binds the tested vulnerable identity to SHA-256 ebf927ca04aa4ea5794dbdcc4f97ce45f184a311d935b1fbf5e6195d4a1b9252, computed from git:https://github.com/curl/curl.git@f8df560ed9faa2ff3d6198b50f55eaf0315fcb39. The observed environment was Linux x86-64, libcurl multi API, wolfSSL 5.8.4, and Python 3's TLS-capable local HTTPS peer. No sanitizer was used.

Recommendations / Next Steps

  • Upgrade to curl 8.22.0 or later.
  • If immediate upgrade is unavailable, apply upstream commit ed0338befd1d865a8ea1fbaa90013a096dedd07a and rebuild libcurl.
  • As a temporary mitigation, avoid combining the wolfSSL backend, CA caching, and CURLOPT_SSL_CTX_FUNCTION trust-store replacement.
  • Retain a regression test that primes a CAfile-only multi-handle cache, installs a callback-selected rejecting store on a fresh transfer, and confirms the policy remains effective on the cache-hit path.
  • Test cache-hit and cache-miss branches independently; cache misses already set the old completion flag and therefore do not expose the same sequence.

Additional Notes

  • The finalized script passed twice consecutively, and each script execution itself ran two vulnerable and two fixed attempts.
  • The callback uses an empty trust store as a deterministic stricter policy. This models the advisory's callback-selected trust store and proves policy state is overridden without relying on application-specific certificate contents.
  • The local HTTPS peer intentionally closes each HTTP connection. CA caching is independent of connection reuse; forcing a fresh TLS connection ensures the second connection reaches the vulnerable cache-hit setup sequence.
  • A compiled-in default CA path initially prevented the cache criteria from being satisfied. The final build explicitly uses --without-ca-bundle --without-ca-path, and the runtime logs confirm CApath: none.

CVE-2026-82208 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.

Event 1/40
0:002:20
0:00
session startedgpt-5.6-sol · CVE-2026-82208 · REPRO-20
0:05
0:06
web search
0:14
0:15
0:17
web search
0:18
web search
0:28
0:29
web search
0:30
web search
0:31
0:32
0:40
0:51
0:52
0:53
web search
0:54
web search
1:07
1:09
1:17
web search
1:21
2:19
2:19
2:19
2:19
2:19
2:19
2:19
2:19
2:19
2:19
extract_facts
no facts extracted
08 · How to Fix

How to Fix CVE-2026-82208

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-82208 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-82208

Is CVE-2026-82208 exploitable?

Yes. Pruva independently reproduced CVE-2026-82208 in curl/curl and verified the exploit fires end-to-end in a sandboxed environment. A runnable proof-of-concept script and the full agent transcript are on this page (reproduction REPRO-2026-00368).

How severe is CVE-2026-82208?

CVE-2026-82208 is rated low severity.

What type of vulnerability is CVE-2026-82208?

CVE-2026-82208 is classified as CWE-295: Improper Certificate Validation. (Improper Certificate Validation).

Which versions of curl/curl are affected by CVE-2026-82208?

curl/curl curl 8.9.1 through 8.21.0 inclusive. is affected by CVE-2026-82208.

How can I reproduce CVE-2026-82208?

Pruva provides a verified reproduction script on this page. Download it and run it inside an isolated environment such as a container or virtual machine — never against production. The reproduction was confirmed end-to-end by Pruva's automated agents.

Is the CVE-2026-82208 reproduction verified?

Yes. Pruva reproduced CVE-2026-82208 with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for CVE-2026-82208

Authoritative sources for CVE-2026-82208 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.