Bouncy Castle can leak a private key through timing: CVE-2024-14041, fixed in 1.78
A timing flaw in Bouncy Castle's post-quantum ML-KEM code can leak a private key. It was already fixed in 1.78 (April 2024); only versions 1.73 to 1.77 are exposed.
Table of contents
A timing flaw in Bouncy Castle's post-quantum ML-KEM code can leak a private key. It was already fixed in 1.78 (April 2024); only versions 1.73 to 1.77 are exposed.
On July 28, 2026, CVE-2024-14041 was published against Bouncy Castle, the standard Java cryptography library. Measuring the tiny differences in how long an operation takes, enough times, lets an attacker reconstruct a private key that should never leave the server.
The headline first: this was fixed in 1.78, released in April 2024. The current release is 1.85, so anything reasonably recent is unaffected. The exposed range is versions 1.73 through 1.77. As the "CVE-2024-" prefix hints, the fix landed more than two years before the identifier did.
Even so, once scanners start picking this ID up, plenty of teams will spend tomorrow morning asking whether they are affected. Below: how to tell, what the flaw actually does, and why a two-year-old fix is only now getting a number.
How to tell whether you are affected
There is exactly one thing to check: the version of org.bouncycastle:bcprov-jdk18on (or the equivalent provider artifact) in your Java projects.
| Version in use | Verdict | Action |
|---|---|---|
| 1.72 and earlier | Not affected | The feature does not exist yet (update anyway, for other reasons) |
| 1.73 β 1.77 | Affected | Move to 1.78 or later (1.85 preferred) |
| 1.78 β 1.84 | Already fixed | Nothing to do for this CVE |
| 1.85 (current) | Already fixed | Nothing to do |
Anything at 1.72 or below is outside the range because the implementation at the centre of this β ML-KEM, previously called Kyber β first shipped in 1.73. Earlier releases simply do not contain the code. That is not a reason to leave them alone, of course; older releases carry other problems.
Severity is 8.2 (high) under the newer CVSS 4.0 scale. No CVSS 3.1 score was published, so some scanners will show no number at all, or their own estimate. If you see conflicting figures, judge by the version table above rather than the score.
A division instruction is enough to leak a key
This is a timing attack: the attacker infers a secret not from what the program outputs but from how long it took.
The pivot is CPU division. On many processors, how long a division takes varies slightly with the numerator. The ML-KEM implementation had several places where a secret value was divided by a well-known fixed number (3329). The divisor is public, but if the numerator is secret, the elapsed time leaks information about it. Observe that across enough exchanges, accumulate it statistically, and the long-term private key itself can be reconstructed.
The issue is known as KyberSlash. Bouncy Castle had three affected sites: Poly.toMsg, which decodes the decrypted message (known as KyberSlash1), and the ciphertext compression routines Poly.compressPoly and PolyVec.compressPolyVec (KyberSlash2). Compression during encapsulation is not affected, because the values it handles become the public ciphertext anyway β leaking them through timing costs nothing. Only the decryption side matters.
The fix is straightforward. Two changes, on December 16, 2023 and January 5, 2024, replaced every division on secret-derived data with a multiply-and-shift sequence, which takes the same time regardless of the values involved. The first commit carries the developer's own note that "there is a chance a division instruction might get generated introducing a timing signal on the secret input."
That post is cryptographer Daniel J. Bernstein publicising the issue in December 2023. KyberSlash was first noticed by the Cryspen team β Goutam Tamvada, Karthikeyan Bhargavan and Franziskus Kiefer β while building a formally verified Kyber implementation; they reported it to pq-crystals, which patched the first site on December 1, 2023. Bernstein found it independently and published a working key-recovery demonstration on December 30 that year. The paper that followed won the CHES 2025 Best Paper Award and reports keys recovered "within minutes for KyberSlash2 and a few hours for KyberSlash1." This is a working attack, not a theoretical one.
Who goes after this, and why
This technique is not available to whoever is scanning the internet for weak servers today. It is usable by someone positioned to send tens or hundreds of thousands of requests to a server that keeps reusing the same key, and to measure each response time precisely. That means a neighbouring virtual machine on the same cloud host, a foothold inside the same network, or a long-running communication relationship with the target.
What they do with it is reassemble the server's long-term private key from the distribution of those measurements. Once they hold the key, they decrypt traffic as a legitimate recipient. No trace of intrusion is left behind: no failed logins, no dropped files. That is the unpleasant part of this class of attack β ordinary monitoring will not see it.
What is lost is the contents of everything that key protected, potentially including traffic captured and stored earlier. That said, assembling those preconditions is genuinely hard, and the scoring reflects it β CVSS 4.0 rates attack complexity high and marks an attack requirement as present. This is not something you stumble into via a mass-exploitation campaign.
Why a two-year-old fix is only now getting a number
The fix landed in early 2024; 1.78 shipped on April 6, 2024. The CVE was published on July 28, 2026. That two-year gap is reasonably uncomfortable to read.
As a matter of fact, the Bouncy Castle project has published no explanation for the delay. The project wiki page the CVE record cites as its vendor advisory does not exist and redirects to the wiki home. There is no GitHub security advisory either.
Two things are verifiable. First, the organisation behind Bouncy Castle became a CVE numbering authority only recently β it has 14 CVEs in total, the earliest published in August 2025. Second, the CVE credits a research team called Robusta. A recorded talk by the project's developer notes that Robusta approached Bouncy Castle in July 2025 with an initial report of 57 possible issues found by a bytecode analyser, and the same team is credited on a separate 2026 flaw (CVE-2026-5598, private-key leakage from non-constant-time comparisons in FrodoKEM).
So the most natural reading of the public record is that a large audit swept up historic fixes that had never been assigned identifiers, and they are now being back-filled. That is our inference, not a vendor statement. It fits the fact that the identifier's year (2024) matches when the fix landed rather than when it was published.
Operationally, none of this is harmful. Retroactively numbering old fixes is a good direction for anyone auditing dependencies. The cost lands elsewhere: a scanner surfaces the ID, someone reads it as a fresh vulnerability, and an unnecessary incident response starts.
The class of flaw that post-quantum migration will keep producing
There is a reason not to file this away as old news. ML-KEM is the flagship of post-quantum cryptography β designed to hold up against future quantum computers, and standardised by NIST as FIPS 203 in 2024 β and governments and major cloud providers are in the middle of migrating to it right now. Google has said publicly that it treats 2029 as the point when current cryptography starts falling (Japanese-language coverage).
What KyberSlash demonstrated is unglamorous but heavy: a scheme can be mathematically sound and still leak its key through how the code is written. The cause here was not advanced cryptanalysis. It was using a division. Newer schemes have shallower implementation experience, so plain oversights like this will keep surfacing β the KyberSlash library tracker still listed unpatched implementations as of August 2025.
One practical note: Bouncy Castle has said that after 1.85 it will drop the pre-standardisation names Kyber, Dilithium and SphincsPlus from the provider in favour of the official ones such as ML-KEM. Naming is in flux during the transition, so search your dependency inventory under both the old and new names to avoid missing anything. Flaws in crypto libraries tend to undermine trust quietly, much as the signature-forgery issue in node-forge did.
What to check now
There is not much to do. In order:
First, count your Bouncy Castle versions. Even if you never declared it directly, other libraries pull it in. Its reach in Java is considerable β public dependency data records over 4,000 dependents for the provider artifact alone, and well-known projects such as the Keycloak identity platform track Bouncy Castle CVE remediation as an ongoing task. Use mvn dependency:tree or gradle dependencies so transitive versions show up too. If you want the dependency sweep to go faster, a paste-your-manifest scanner can help β though that one covers npm and Python, so Java still needs the commands above.
Second, plan an update only if 1.73 to 1.77 turns up. You could go further and check whether that code path actually performs ML-KEM decapsulation, but working that out will usually cost more time than simply moving to 1.85.
Third, if you are on 1.78 or later, write it down and close it. Recording that this ID is already remediated saves you repeating the exercise the next time a different tool surfaces it. In terms of how much noise a serious Java library flaw deserves, this is nothing like the Fastjson takeover β that one is unauthenticated and immediate, this one is a narrowly conditioned leak. Treat their urgency separately. The flaw is not in CISA's catalogue of vulnerabilities confirmed to be under attack (KEV), and no exploitation has been reported.
Summary
CVE-2024-14041 covers three places in Bouncy Castle's ML-KEM implementation where a private key could leak through timing. Severity is 8.2 on CVSS 4.0. The affected range is 1.73 through 1.77, and it was fixed in 1.78 back in April 2024; the current release is 1.85. Exploitation requires a position from which you can precisely time a very large number of exchanges against the same key β not a mass-exploitation scenario.
The work is to count versions in your dependency tree and confirm nothing sits in 1.73β1.77. If nothing does, record it and move on. The part worth remembering is not the flaw itself but the principle behind it: a mathematically sound cipher can still surrender its key over a single line of implementation. As post-quantum migration accelerates, findings shaped like this one will keep arriving. We will update this article if new information appears.
Sources
- βΈ NVD - CVE-2024-14041
- βΈ KyberSlash - project page (Daniel J. Bernstein and others)
- βΈ KyberSlash - per-library patch status
- βΈ bc-java - KyberSlash1 fix commit (Poly.toMsg)
- βΈ bc-java - KyberSlash2 fix commit (compression routines)
- βΈ Bouncy Castle - Java downloads and release notes
- βΈ "KyberSlash: Exploiting secret-dependent division timings in Kyber implementations" (TCHES 2025, CHES 2025 Best Paper)
- βΈ NVD - CVE-2026-5598 (FrodoKEM issue reported by the same Robusta team)

Makoto Horikawa
Backend Engineer / AWS / Django