Skip to content

CVE-2026-5479: Verified Reproduction

CVE-2026-5479: wolfSSL: EVP ChaCha20-Poly1305 decryption returns plaintext without verifying authentication tag

CVE-2026-5479 is verified against wolfssl · source. Affected versions: < 5.9.1. Fixed in 5.9.1. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00172.

REPRO-2026-00172 wolfssl · source May 28, 2026 CVE entry .txt
Severity
HIGH
CVSS
8.1
Reproduced in
12m 46s
Tool calls
175
Spend
$2.22
01 · Overview

What Is CVE-2026-5479?

CVE-2026-5479 (CWE-354) is a high-severity vulnerability in wolfSSL's EVP compatibility API where ChaCha20-Poly1305 decryption returns plaintext to the caller without verifying that the Poly1305 authentication tag matches, silently defeating the AEAD's authenticity guarantee. Pruva reproduced it (reproduction REPRO-2026-00172).

02 · Severity & CVSS

CVE-2026-5479 Severity & CVSS Score

CVE-2026-5479 is rated high severity, with a CVSS base score of 8.1 out of 10.

HIGH threat level
8.1 / 10 CVSS base
Weakness CWE-354 (Improper Validation of Integrity Check Value)

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected wolfssl Versions

wolfssl · source versions < 5.9.1 are affected.

How to Reproduce CVE-2026-5479

$ pruva-verify REPRO-2026-00172
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00172/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-5479

Reproduced
Vulnerable wolfSSL v5.9.0-stable
Fixed wolfSSL v5.9.1-stable
How the agent worked 571 events · 175 tool calls · 13 min
13 minDuration
175Tool calls
130Reasoning steps
571Events
2Dead-ends
Agent activity over 13 min
Support
18
Repro
312
Variant
236
0:0012:46

Root Cause and Exploit Chain for CVE-2026-5479

Versions: wolfSSL < 5.9.1 (last vulnerable release tag: v5.9.0-stable).Fixed: 5.9.1 (commit 1faddd640).

CVE-2026-5479 is an integrity-check bypass (CWE-354) in wolfSSL's EVP compatibility layer for ChaCha20-Poly1305 AEAD decryption. In wolfSSL_EVP_CipherFinal (wolfcrypt/src/evp.c), the decrypt path for WC_CHACHA20_POLY1305_TYPE calls wc_ChaCha20Poly1305_Final() to compute the Poly1305 authentication tag, which overwrites the expected tag previously stored in ctx->authTag by EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG). No comparison between the computed tag and the expected tag is ever performed, so any forged or mismatched tag is silently accepted. This completely nullifies the authenticity guarantee of the AEAD cipher, allowing an active network adversary to supply modified ciphertext that the application will treat as integrity-validated.

  • Package/component affected: wolfSSL libwolfssl, specifically the EVP compatibility API (wolfSSL_EVP_CipherFinal) for ChaCha20-Poly1305 decryption.
  • Affected versions: wolfSSL < 5.9.1 (last vulnerable release tag: v5.9.0-stable).
  • Fixed versions: 5.9.1 (commit 1faddd640).
  • Risk level: High (CVSS 3.1: 8.1, CVSS 4.0: 7.6).
  • Consequences: Any consumer using the standard EVP decrypt pattern (EVP_DecryptInit_exEVP_DecryptUpdateEVP_CIPHER_CTX_ctrl(SET_TAG)EVP_DecryptFinal_ex) will accept attacker-modified ciphertext as authentic. This enables message forgery in protocols that rely on ChaCha20-Poly1305 via the wolfSSL EVP API (e.g., TLS record-layer AEAD when used through the EVP abstraction).

Root Cause

The bug is located in wolfcrypt/src/evp.c inside the wolfSSL_EVP_CipherFinal function, specifically in the WC_CHACHA20_POLY1305_TYPE branch (lines ~1502–1515 in v5.9.0-stable).

On the decrypt path (!ctx->enc), the code does:

case WC_CHACHA20_POLY1305_TYPE:
    if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly,
                                  ctx->authTag) != 0) {
        WOLFSSL_MSG("wc_ChaCha20Poly1305_Final failed");
        return WOLFSSL_FAILURE;
    }
    else {
        *outl = 0;
        return WOLFSSL_SUCCESS;
    }
    break;

wc_ChaCha20Poly1305_Final() computes the Poly1305 tag and writes it into ctx->authTag, overwriting the expected tag that was set earlier via EVP_CTRL_AEAD_SET_TAG. The code then unconditionally returns WOLFSSL_SUCCESS without ever comparing the computed tag to the expected tag.

The fix (commit 1faddd640edc8195c1fb7cb3904876e434ecab87, PR #10102) mirrors the existing AES-GCM branch: it saves the expected tag before calling _Final(), then uses wc_ChaCha20Poly1305_CheckTag() to verify the computed tag against the saved expected tag on the decrypt path. If the tags do not match, WOLFSSL_FAILURE is returned.

Diff excerpt from the fix:

+        {
+            byte computedTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
+            if (!ctx->enc) {
+                XMEMCPY(computedTag, ctx->authTag, sizeof(computedTag));
+            }
             if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly,
                                           ctx->authTag) != 0) {
                 WOLFSSL_MSG("wc_ChaCha20Poly1305_Final failed");
                 return WOLFSSL_FAILURE;
             }
-            else {
-                *outl = 0;
-                return WOLFSSL_SUCCESS;
+            if (!ctx->enc) {
+                int tagErr = wc_ChaCha20Poly1305_CheckTag(computedTag,
+                                                          ctx->authTag);
+                ForceZero(computedTag, sizeof(computedTag));
+                if (tagErr != 0) {
+                    WOLFSSL_MSG("ChaCha20-Poly1305 tag mismatch");
+                    return WOLFSSL_FAILURE;
+                }
             }
-            break;
+            *outl = 0;
+            return WOLFSSL_SUCCESS;
+        }
+        break;

Reproduction Steps

  1. Run repro/reproduction_steps.sh. This self-contained script:

    • Builds vulnerable wolfSSL (v5.9.0-stable) into /tmp/wolfssl-vuln and fixed wolfSSL (v5.9.1-stable) into /tmp/wolfssl-fixed (or uses pre-built installations if present).
    • Compiles repro/aead_tag_check.c against both libraries.
    • Executes the test harness against each build.
    • Generates logs/runtime_manifest.json with concrete API return values.
    • Prints a verdict based on observable cryptographic behavior.
  2. What the script does:

    • Encrypts a known plaintext under ChaCha20-Poly1305 with a fixed key/nonce.
    • Performs three tamper attacks on the ciphertext/tag pair:
      1. Replaces the 16-byte authentication tag with all zeros.
      2. Replaces the tag with a random bad tag (0xAB repeated).
      3. Flips the first byte of the ciphertext while keeping the original tag.
    • Decrypts each tampered pair using the standard EVP API (EVP_DecryptInit_exEVP_DecryptUpdateEVP_CIPHER_CTX_ctrl(SET_TAG)EVP_DecryptFinal_ex).
    • Captures the return value of EVP_DecryptFinal_ex and the decrypted bytes.
  3. Expected evidence:

    • Vulnerable build: EVP_DecryptFinal_ex returns 1 (success) for all three tampered inputs, and the decrypted plaintext is delivered to the caller (either matching the original plaintext for forged tags, or producing modified bytes for flipped ciphertext).
    • Fixed build: EVP_DecryptFinal_ex returns 0 (failure) for all three tampered inputs, correctly rejecting the forgeries.

Evidence

  • Vulnerable run log: logs/vulnerable_output.txt

    • Excerpt (Test 1 — zeroed tag):
      EVP_DecryptUpdate ret=1, EVP_DecryptFinal_ex ret=1
      Decrypted:  54686520717569636b2062726f776e20666f78206a756d7073206f7665720000
      Plaintext match: YES
      VULNERABLE: YES (Final succeeded with forged tag)
      
    • Excerpt (Test 3 — flipped ciphertext byte):
      EVP_DecryptUpdate ret=1, EVP_DecryptFinal_ex ret=1
      Decrypted:  ab686520717569636b2062726f776e20666f78206a756d7073206f7665720000
      Plaintext match: NO
      VULNERABLE: YES (Final succeeded with modified ciphertext)
      
  • Fixed run log: logs/fixed_output.txt

    • Excerpt (Test 1 — zeroed tag):
      EVP_DecryptUpdate ret=1, EVP_DecryptFinal_ex ret=0
      Decrypted:  54686520717569636b2062726f776e20666f78206a756d7073206f7665720000
      Plaintext match: YES
      VULNERABLE: NO (Final rejected forged tag)
      
  • Runtime manifest: logs/runtime_manifest.json

    • Contains structured JSON with the exact EVP_DecryptFinal_ex return codes for each tamper strategy on both the vulnerable and fixed builds.
  • Environment:

    • Host: x86_64-pc-linux-gnu
    • Compiler: gcc
    • wolfSSL configure flags: --enable-chacha --enable-poly1305 --enable-aesgcm --enable-opensslextra --disable-shared --enable-static --enable-debug CFLAGS='-g -O0'

Recommendations / Next Steps

  1. Upgrade immediately to wolfSSL 5.9.1 or later, which contains commit 1faddd640.
  2. Verify tag-check coverage in any custom fork or wrapper around wolfSSL_EVP_CipherFinal for ChaCha20-Poly1305; the missing wc_ChaCha20Poly1305_CheckTag() call is the root cause.
  3. Regression testing: Add the exact tamper strategies from this reproduction (zeroed tag, random tag, flipped ciphertext byte) to the project's EVP cipher unit tests. The upstream fix already includes a negative test for an all-zero forged tag.
  4. Audit other AEAD paths: Review wolfSSL_EVP_CipherFinal for any other AEAD ciphers that might lack tag verification. The AES-GCM branch already had the correct pattern; ChaCha20-Poly1305 was the outlier.

Additional Notes

  • Idempotency: repro/reproduction_steps.sh was executed twice consecutively on the same host and produced identical results (exit code 0, VERDICT: CONFIRMED).
  • Edge cases: The reproduction uses the standard EVP_DecryptInit_ex + EVP_DecryptUpdate + EVP_DecryptFinal_ex pattern. The streaming EVP_CipherUpdate/EVP_CipherFinal equivalents are also affected because they route through the same wolfSSL_EVP_CipherFinal code path.
  • Limitations: The reproduction requires building wolfSSL from source with --enable-chacha --enable-poly1305 --enable-opensslextra. On systems without a C compiler or git, the script will exit with a descriptive error rather than a false positive.

CVE-2026-5479 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:000:23
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-5479 · cve-2026
0:04
0:04
web search
0:04
error

Unknown error

0:06
0:06
0:06
error

Unknown error

0:16
0:16
extract_facts
no facts extracted
0:16
0:16
0:16
supportrepro
0:18
0:19
0:19
0:19
0:20
0:20
0:20
0:20
0:21
0:21
0:23
08 · How to Fix

How to Fix CVE-2026-5479

Upgrade wolfssl · source to 5.9.1 or later.

Coming soon

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

10 · FAQ

FAQ: CVE-2026-5479

How does the CVE-2026-5479 tag-bypass attack work?

A consumer using the standard EVP pattern (EVP_DecryptInit_ex -> EVP_DecryptUpdate -> EVP_CIPHER_CTX_ctrl(SET_TAG) -> EVP_DecryptFinal_ex) will see EVP_DecryptFinal_ex return success even for ciphertext with a mismatched tag or flipped bytes, because the expected tag is overwritten before any comparison happens. An active network attacker who can supply or modify ciphertext (e.g. in a TLS record-layer AEAD context using wolfSSL's EVP API) can therefore forge messages that the application treats as integrity-validated.

Which wolfSSL versions are affected by CVE-2026-5479, and where is it fixed?

wolfSSL versions before 5.9.1 are affected (last vulnerable release tag v5.9.0-stable). It is fixed in 5.9.1 (commit 1faddd640).

How severe is CVE-2026-5479?

The record rates it high severity; the underlying root-cause analysis cites CVSS 3.1 score 8.1 and CVSS 4.0 score 7.6.

How can I reproduce CVE-2026-5479?

Download the verified script from this page and run it in an isolated environment against wolfSSL before 5.9.1. It performs a standard EVP ChaCha20-Poly1305 decrypt with a deliberately mismatched or tampered authentication tag and shows EVP_DecryptFinal_ex succeeding anyway, then confirms 5.9.1 rejects the same input.
11 · References

References for CVE-2026-5479

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