CVE-2026-59648 Overview
CVE-2026-59648 is a resource exhaustion vulnerability in the Bouncy Castle cryptographic library for Java. The flaw resides in the OpenPGP Argon2 String-to-Key (S2K) implementation, which honours attacker-chosen memory and pass parameters read from unauthenticated packets. An attacker can craft a passphrase-encrypted OpenPGP message with maximum Argon2 cost values, forcing the target to allocate up to 1 TiB of heap and consume unbounded CPU during key derivation. The issue is classified under CWE-770: Allocation of Resources Without Limits or Throttling.
Critical Impact
A single unauthenticated OpenPGP message can exhaust heap memory and CPU on any Java host that decrypts it using Bouncy Castle, leading to denial of service.
Affected Products
- Bouncy Castle for Java before 1.85
- Bouncy Castle for Java LTS before 2.73.12
- Bouncy Castle for Java FIPS (BC-FJA) before bcpg-fips 1.0.13, 2.0.13, and 2.1.13
Discovery Timeline
- 2026-08-03 - CVE-2026-59648 published to NVD
- 2026-08-04 - Last updated in NVD database
Technical Details for CVE-2026-59648
Vulnerability Analysis
The OpenPGP Argon2 S2K specifier encodes three cost parameters as single bytes: memory exponent, passes (iterations), and parallelism (lanes). Each field accepts values up to 255. Bouncy Castle previously read these values from an untrusted OpenPGP packet and passed them directly into Argon2BytesGenerator before the message had been authenticated.
An attacker supplying a memory exponent of 30 forces allocation of 2^30 KiB (1 TiB) of working memory for a single decrypt attempt. The passes and parallelism fields were similarly unbounded, allowing arbitrary CPU consumption. The library exposes only the MAX_MEMORY_EXP cap for memory, which historically defaulted to 30.
Root Cause
The root cause is missing input validation on cost parameters supplied by an unauthenticated source. OpenPGP Argon2 key derivation runs before the message MAC can be verified, so the library must independently bound the cost inputs. The prior implementation trusted the packet fields.
Attack Vector
An attacker sends a passphrase-encrypted OpenPGP message with maximum Argon2 cost parameters to any service or client that decrypts PGP messages using Bouncy Castle. Examples include mail gateways, key management systems, and file-processing pipelines. The victim does not need to know the passphrase; the resource exhaustion occurs during key derivation before any decryption succeeds.
// Patch excerpt from Argon2Parameters.java
// Source: https://github.com/bcgit/bc-java/commit/c915cc3f7a8d58f5ea2f88f01dfef2d402dd0799
/**
* System/security property setting the maximum permitted memory exponent
* (i.e. memory <= 1 << MAX_MEMORY_EXP). Defaults to 24 (16 GiB); the property
* may be raised up to a ceiling of 30. The default was lowered from the
* historical 30 (1 TiB) so that a single key derivation driven by
* attacker-chosen cost parameters - notably an OpenPGP Argon2 S2K specifier
* read from an unauthenticated packet - cannot exhaust the heap of a typical host.
*/
public static final String MAX_MEMORY_EXP = "org.bouncycastle.argon2.max_memory_exp";
/**
* Bounds the number of Argon2 passes accepted from untrusted cost parameters.
* Defaults to 10; OpenPGP key derivation rejects larger values.
*/
public static final String MAX_PASSES = "org.bouncycastle.argon2.max_passes";
/**
* Bounds the Argon2 parallelism (lanes) accepted from untrusted cost parameters.
* Defaults to 16.
*/
public static final String MAX_PARALLELISM = "org.bouncycastle.argon2.max_parallelism";
Detection Methods for CVE-2026-59648
Indicators of Compromise
- Java processes exhibiting sudden heap growth to multi-gigabyte or terabyte-scale allocations during OpenPGP decrypt operations
- OutOfMemoryError exceptions originating from org.bouncycastle.crypto.generators.Argon2BytesGenerator or fillMemoryBlocks
- Sustained CPU saturation on a single thread during PGP message parsing
- Inbound PGP messages with Argon2 S2K specifiers containing high memory exponent, pass, or parallelism byte values
Detection Strategies
- Inspect Java heap dumps and thread stacks for Argon2BytesGenerator frames during unexplained memory spikes
- Parse OpenPGP packet headers on ingress and flag S2K type 4 (Argon2) with memory exponent above 24, passes above 10, or parallelism above 16
- Enumerate deployed bcprov-jdk*.jar, bcpg-jdk*.jar, and bcpg-fips-*.jar artifacts across build systems and runtime environments
Monitoring Recommendations
- Enable JVM garbage collection and out-of-memory logging on services that decrypt PGP content
- Track process memory ceilings on mail gateways, backup systems, and CI/CD pipelines that handle GPG-encrypted artifacts
- Alert on repeated PGP decrypt failures accompanied by resource pressure from the same source
How to Mitigate CVE-2026-59648
Immediate Actions Required
- Upgrade Bouncy Castle for Java to 1.85 or later
- Upgrade Bouncy Castle for Java LTS to 2.73.12 or later
- Upgrade Bouncy Castle for Java FIPS to bcpg-fips 1.0.13, 2.0.13, or 2.1.13 depending on the deployed series
- Audit transitive dependencies; Bouncy Castle is frequently pulled in by third-party libraries
Patch Information
The fix is in commit c915cc3f7a8d58f5ea2f88f01dfef2d402dd0799. The patch lowers the default MAX_MEMORY_EXP from 30 to 24 (16 GiB ceiling) and introduces two new bounds: MAX_PASSES (default 10) and MAX_PARALLELISM (default 16). OpenPGP key derivation now rejects messages exceeding any active limit with a PGPException rather than processing them. See the CVE-2026-59648 wiki entry for full advisory details.
Workarounds
- Set the system properties org.bouncycastle.argon2.max_memory_exp, org.bouncycastle.argon2.max_passes, and org.bouncycastle.argon2.max_parallelism to conservative values after upgrading
- Constrain the JVM maximum heap with -Xmx on services that decrypt PGP messages so a single request cannot consume all host memory
- Filter or reject inbound OpenPGP messages that use Argon2 S2K if the application does not require it
# Enforce conservative Argon2 cost bounds on the JVM command line
java \
-Dorg.bouncycastle.argon2.max_memory_exp=20 \
-Dorg.bouncycastle.argon2.max_passes=4 \
-Dorg.bouncycastle.argon2.max_parallelism=8 \
-Xmx2g \
-jar your-application.jar
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

