high · 8.1CVE-2026-61798Aug 20, 2026

CVE-2026-61798: netty-incubator-codec-ohttp BoringSSL HPKE Private Key Exposure via toString()

Shubham Kandhare
Security Engagement Manager, SecureLayer7

The Netty OHTTP BoringSSL codec leaks raw HPKE private key bytes into log files and exception messages because toString() on key objects renders the full key byte array in plaintext.

Packageio.netty.incubator:netty-incubator-codec-ohttp-hpke-classes-boringssl
Ecosystemmaven
Affected<= 0.0.22.Final
Fixed in0.0.23.Final
CVE-2026-61798: netty-incubator-codec-ohttp BoringSSL HPKE Private Key Exposure via toString()

The problem

In netty-incubator-codec-ohttp-hpke-classes-boringssl versions up to 0.0.22.Final, two classes expose private key material in cleartext.

BoringSSLAsymmetricKeyParameter.toString() calls Arrays.toString(bytes) unconditionally, even when isPrivate=true. BoringSSLAsymmetricCipherKeyPair.toString() then concatenates that private-key object directly into its own string output.

A third path in BoringSSL.EVP_HPKE_KEY_init_or_throw() includes Arrays.toString(privateKeyBytes) in the IllegalArgumentException message when BoringSSL rejects the key. Any logging framework that records key-pair objects or caught exceptions will persist full HPKE private key bytes to disk.

Proof of concept

A working proof-of-concept for CVE-2026-61798 in io.netty.incubator:netty-incubator-codec-ohttp-hpke-classes-boringssl, with the exact payload below.

java
// Run inside the io.netty.incubator.codec.hpke.boringssl package.
// No exploit delivery needed: the vulnerability fires on any toString() or log call.

public final class VerifyPrivateKeyToString {
  public static void main(String[] args) {
    byte[] privateKey = new byte[] {1, 2, 3, 4};
    byte[] publicKey  = new byte[] {5, 6, 7, 8};
    BoringSSLAsymmetricCipherKeyPair pair =
        new BoringSSLAsymmetricCipherKeyPair(privateKey, publicKey);
    // Any logger.debug(pair) or System.out.println(pair) produces:
    System.out.println(pair.toString());
    // Output:
    // BoringSSLAsymmetricCipherKeyPair{privateKey=BoringSSLAsymmetricKeyParameter{bytes=[1, 2, 3, 4], isPrivate=true}, publicKey=BoringSSLAsymmetricKeyParameter{bytes=[5, 6, 7, 8], isPrivate=false}}

    // Second path: pass a malformed key to trigger the exception message.
    // EVP_HPKE_KEY_init_or_throw will throw:
    // IllegalArgumentException: privateKeyBytes does not contain a valid private key: [1, 2, 3, 4]
  }
}

The root cause is CWE-532 (Insertion of Sensitive Information into Log File) combined with CWE-312 (Cleartext Storage of Sensitive Information). Java logging frameworks call toString() automatically on structured objects passed as log arguments, so no explicit string conversion is required from the caller.

The patch in 0.0.23.Final replaces the private-key byte array in BoringSSLAsymmetricKeyParameter.toString() with a redacted placeholder when isPrivate is true, removes the private-key field from BoringSSLAsymmetricCipherKeyPair.toString(), and strips Arrays.toString(privateKeyBytes) from the EVP_HPKE_KEY_init_or_throw exception message.

Regression tests were also added to assert that neither toString() output nor exception messages contain private key values.

The fix

Upgrade io.netty.incubator:netty-incubator-codec-ohttp-hpke-classes-boringssl to 0.0.23.Final. No configuration workaround exists for earlier versions; the leak is in library internals. As a temporary mitigation, avoid logging key-pair objects or exceptions that contain key material, and review existing log pipelines for historical key exposure.

Reporter not attributed.

References: [1][2][3]

Related research