Skip to content

CVE-2026-44699: Verified Repro With Script Download

CVE-2026-44699: libjwt: JWT algorithm-confusion authentication bypass via RSA JWK without alg

CVE-2026-44699 is verified against libjwt · c. Affected versions: >= 3.0.0, <= 3.3.2. Fixed in 3.3.3. Vulnerability class: Auth Bypass. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00139.

REPRO-2026-00139 libjwt · c Auth Bypass May 22, 2026 CVE entry ↗ .txt
Severity
CRITICAL
CVSS
9.1
Reproduced in
13m 26s
Tool calls
106
Spend
$0.94
01 · Overview

What Is CVE-2026-44699?

CVE-2026-44699 is a critical (CVSS 9.1 per the advisory) JWT algorithm-confusion authentication bypass (CWE-347) in libjwt, a C library for JWT processing. An RSA JWK lacking an alg parameter can be forged into a valid HMAC-signed token using only the public JWKS. Pruva reproduced it (reproduction REPRO-2026-00139).

02 · Severity & CVSS

CVE-2026-44699 Severity & CVSS Score

CVE-2026-44699 is rated critical severity, with a CVSS base score of 9.1 out of 10.

CRITICAL threat level
9.1 / 10 CVSS base
Weakness CWE-347 (Improper Verification of Cryptographic Signature)

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

03 · Affected Versions

Affected libjwt Versions

libjwt · c versions >= 3.0.0, <= 3.3.2 are affected.

How to Reproduce CVE-2026-44699

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

Reproduced by Pruva's autonomous agents — 106 tool calls over 13 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 371 events · 106 tool calls · 13 min
13 minDuration
106Tool calls
87Reasoning steps
371Events
Agent activity over 13 min
Support
17
Repro
142
Variant
208
0:0013:26

Root Cause and Exploit Chain for CVE-2026-44699

Summary

libjwt versions 3.0.0 through 3.3.2 suffer from an algorithm confusion attack that allows JWT forgery using only a public RSA JWK. When an RSA JWK lacking an alg parameter is supplied as the verification key for an HMAC-signed token (HS256/HS384/HS512), the library incorrectly accepts the RSA key for HMAC verification. Because the internal jwk_item_t union shares storage between provider_data (an RSA EVP_PKEY*) and oct.{key,len} (HMAC bytes/length), the HMAC path reads a zero-length key and produces a successful verification for any token signed as HMAC("", header.payload). An attacker who knows only the published JWKS can forge valid tokens and bypass authentication.

Impact

  • Package: libjwt (C library for JWT processing)
  • Affected versions: 3.0.0 through 3.3.2 (inclusive)
  • Fixed version: 3.3.3
  • Risk level: Critical (CVSS 3.1 base 9.1)
  • Consequences: Full authentication bypass. Any attacker with access to the public JWKS (which is public by definition) can forge HMAC-signed JWTs that the vulnerable library accepts as valid.

Root Cause

The root cause is a failure to validate that a JWK's actual key type (kty) is compatible with the JWT algorithm being used for verification. The library previously relied on the optional alg parameter in the JWK to determine compatibility. When alg was absent (JWT_ALG_NONE), __setkey_check() in jwt-common.c allowed the key to be used with any caller-specified algorithm.

Because jwk_item_t is implemented as a union, setting an RSA key populates provider_data while leaving the HMAC oct fields uninitialized (effectively zero-length). When the HMAC verification backend later runs, it reads oct.key and oct.len, producing an HMAC with an empty key. Since HMAC("", data) is deterministic, an attacker can pre-compute the signature and forge a valid token.

Fix commit
  • Commit 49c730a in the libjwt repository: "Fix algorithm confusion that allows JWT forgery via RSA JWK as HMAC key"
  • The fix introduces jwt_alg_required_kty() which maps each JWA algorithm to its required JWK key type (e.g., HS256 requires kty=oct).
  • __setkey_check() now rejects any setkey/verify callback that pairs a non-none algorithm with an incompatible kty.
  • __verify_config_post() adds a defensive re-check once jwt->alg is bound from the token header.
  • __check_hmac() adds a final backstop refusing any non-oct key for HMAC algorithms.

Reproduction Steps

  1. Execute repro/reproduction_steps.sh
  2. The script builds two versions of libjwt:
    • v3.3.2 (vulnerable)
    • v3.3.3 (fixed)
  3. It compiles a small C harness against each version.
  4. The harness:
    • parses an RSA public JWK without an alg field,
    • calls jwt_checker_setkey(checker, JWT_ALG_HS256, rsa_jwk),
    • verifies a forged HS256 token whose signature is HMAC-SHA256("", header.payload).
  5. On the vulnerable build, the forged token verifies successfully (harness exits 0).
  6. On the fixed build, setkey is rejected immediately with "Key type does not match algorithm" (harness exits 2).

Evidence

Log locations
  • logs/vuln_out.txt — output from harness linked against v3.3.2
  • logs/fix_out.txt — output from harness linked against v3.3.3
  • logs/results.txt — combined summary
  • repro/validation_verdict.json — structured verdict
Key excerpts

Vulnerable build (v3.3.2)

Exit code: 0
VERIFY SUCCEEDED (VULNERABLE)

Fixed build (v3.3.3)

Exit code: 2
setkey rejected: Key type does not match algorithm

These outputs confirm the bug and its remediation: the vulnerable library silently accepts an RSA JWK for HMAC verification and validates the forged token, while the fixed library rejects the key/algorithm mismatch at setkey time.

Environment
  • OS: Ubuntu Noble (24.04)
  • Compiler: GCC 13.3.0
  • CMake: 3.28.3
  • OpenSSL: 3.0.13
  • Jansson: 2.14
  • libjwt built from source at external/libjwt

Recommendations / Next Steps

  1. Upgrade immediately to libjwt >= 3.3.3.
  2. Review JWKS handling in applications that use libjwt. Ensure that verification callbacks do not blindly trust the alg field from an attacker-controlled JWT header without also checking the JWK's kty.
  3. Regression tests: The fix commit includes a comprehensive test suite in tests/jwt_security.c covering RSA, EC, and OKP keys mis-targeted at HMAC algorithms, as well as malformed JWKs where alg disagrees with kty. Maintainers should ensure these tests are run in CI.
  4. Defense in depth: Even after upgrading, applications should enforce algorithm whitelisting (e.g., only accept RS256 if the JWKS contains RSA keys) at the application layer to reduce the impact of any future confusion bugs.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively with identical results, confirming the build and test process is deterministic.
  • Edge cases: The advisory notes the bug specifically requires an RSA JWK without an alg parameter. An RSA JWK that explicitly declares "alg": "RS256" would also be rejected for HMAC after the fix, because the fix binds algorithm acceptance to the JWK's kty, not its optional alg hint.
  • Limitations: The reproduction script focuses on HS256 with a 2048-bit RSA JWK. The fix commit's tests confirm the same issue exists for HS384 and HS512, as well as for EC and OKP keys misused as HMAC keys.

CVE-2026-44699 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:001:12
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-44699 · cve-2026
0:03
0:05
0:07
web search
0:15
0:16
web search
0:54
0:54
extract_facts
no facts extracted
0:59
0:59
0:59
supportrepro
1:01
1:02
1:02
1:02
1:03
1:03
1:03
1:06
1:06
$mkdir -p external && cd external && git clone --depth=100 https://github.com/benmcollins/libjwt.git
0.4s
Cloning into 'libjwt'...
1:12

Artifacts and Evidence for CVE-2026-44699

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-44699

Upgrade libjwt · c to 3.3.3 or later.

Coming soon

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

10 · FAQ

FAQ: CVE-2026-44699

How does the CVE-2026-44699 algorithm-confusion attack work?

An attacker who knows only the published, public RSA JWK forges a token signed as HMAC(\"\", header.payload) — HMAC with an empty key. Because libjwt 3.0.0-3.3.2 accepted the alg-less RSA key for HMAC verification with a zero-length secret, this forged token verifies as valid, giving a full authentication bypass.

Which versions of libjwt are affected by CVE-2026-44699, and where is it fixed?

libjwt versions 3.0.0 through 3.3.2 are affected. It is fixed in 3.3.3.

How severe is CVE-2026-44699?

Critical, CVSS 9.1 per the advisory — a full authentication bypass for any deployment that publishes an RSA JWK without an alg parameter.

How can I reproduce CVE-2026-44699?

Download the verified script from this page and run it in an isolated environment against libjwt 3.0.0-3.3.2 with an RSA JWK that omits the alg parameter. Forge a token using HS256/HS384/HS512 signed with an empty secret and confirm libjwt verifies it as valid; confirm 3.3.3 rejects it.
11 · References

References for CVE-2026-44699

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