There is a particular kind of vulnerability that punishes the careful. CVE-2026-48040, a CVSS 9.1 flaw in the netty-incubator-codec-ohttp library, is one of them: it only fires when an operator has deliberately hardened the JVM by taking away sun.misc.Unsafe, a step many security teams take precisely to reduce their attack surface. In those configurations, an unauthenticated attacker can read and corrupt memory belonging to other people's connections.

The library at issue implements Oblivious HTTP — RFC 9458, the privacy protocol that separates who is making a request from what the request contains — on top of BoringSSL's HPKE C implementation, reached from Java through JNI. To hand encrypted bytes to native code, Netty needs the raw memory address of the buffer holding them. On a standard HotSpot JVM with Unsafe available, direct byte buffers expose that address cleanly. The bug is in what happens when they do not.

"Under the enabling JVM configuration, an unauthenticated network attacker can cause the OHTTP gateway to corrupt memory belonging to other concurrent connections and disclose the contents of adjacent pooled direct buffers by triggering cryptographic operations with crafted OHTTP requests. The corruption occurs regardless of whether the AEAD tag verification succeeds, as BoringSSL zeroizes the output buffer on failure."— NVD, source

The enabling condition is the crux. Per the NVD record, versions before 0.0.22.Final "provide a fallback path for direct ByteBufs that do not expose their memory address through hasMemoryAddress()." That fallback runs when Unsafe is unavailable — for instance "when the JVM is started with -Dio.netty.noUnsafe=true, when a SecurityManager restricts Unsafe access, or when running on non-HotSpot JVMs." In those modes Netty's default PooledByteBufAllocator hands back PooledDirectByteBuf instances whose hasMemoryAddress() returns false, and the fallback computes a native address that does not correspond to the buffer the cryptographic operation should be touching.

Why pooled buffers make this a confidentiality disaster

A miscomputed memory address is a memory-safety bug. What makes this one a cross-connection breach is the word pooled. Netty's high-performance allocator does not hand each connection a fresh, isolated chunk of memory; it carves buffers out of shared arenas to avoid the cost of constant allocation. So when the OHTTP codec reads or writes at the wrong offset, the neighboring bytes it touches do not belong to scratch space — they belong to other live connections sharing the same arena. The result, in the words of the advisory, is that the flaw "violates the confidentiality and integrity of all connections sharing the same Netty buffer arena."

The detail that the corruption "occurs regardless of whether the AEAD tag verification succeeds" is what removes the attacker's last hurdle. Normally, a forged ciphertext fails authentication and is discarded. Here, because BoringSSL zeroizes the output buffer on failure and the output buffer is pointed at someone else's memory, even a deliberately invalid request mutates adjacent data. And as the NVD entry goes on to explain, "the information disclosure path provides the attacker with the encryption key needed to extract the leaked data" — meaning the leak is not just random bytes but recoverable plaintext from other sessions.

Reading the severity

The CVSS vector is AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N. Network reachable, low complexity, no privileges, no user interaction, with high confidentiality and integrity impact — but, notably, no availability impact and an unchanged scope, which is why the score lands at 9.1 rather than a perfect 10. The weakness types assigned, CWE-125 (out-of-bounds read) and CWE-787 (out-of-bounds write), capture both halves of the problem: the attacker can read what they should not and write where they should not.

The single biggest factor in any organization's real-world exposure is whether it runs in the enabling configuration. Plenty of production deployments leave Unsafe available and never touch the fallback path. But the configurations that disable it are not exotic; they are exactly the postures that come up in locked-down, policy-driven, or alternative-runtime environments — the -Dio.netty.noUnsafe=true flag, a restrictive SecurityManager, or a non-HotSpot JVM. An OHTTP gateway is also, by its nature, internet-facing and unauthenticated, since the whole point of the protocol is to relay requests from clients the gateway does not authenticate. That combination — a deliberately hardened, internet-exposed gateway — is the worst case, and it is not hypothetical.

What to do

Version 0.0.22.Final fixes the issue, and the upgrade is the clear remediation. The vendor commit and the project's security advisory (GHSA-32hf-8jw3-v4qq) are linked from the NVD entry. Operators who cannot upgrade immediately and who are running the enabling configuration face an uncomfortable choice: re-enabling Unsafe sidesteps the vulnerable fallback but undoes a deliberate hardening decision, so it should be treated as a temporary measure pending the patch, not a permanent posture. The cleaner path is simply to ship 0.0.22.Final.

It is also worth noting where this sits in the dependency graph. The affected package is an incubator codec — experimental, ahead of the mainline Netty release train — which means the population running it skews toward early adopters of Oblivious HTTP, relay operators, and privacy-infrastructure builders rather than the general Netty user base. That narrows the blast radius in absolute terms, but it also means the affected operators tend to be running privacy-sensitive gateways where a cross-connection plaintext leak is especially damaging to the trust model they are selling. An OHTTP relay that quietly discloses the contents of one client's request to an attacker has failed at the one thing it exists to do. Anyone running the incubator codec should audit not just their version but their JVM flags, because the configuration is the trigger and the version is only the cure.

The lesson here is one the platform-security community keeps relearning: hardening flags interact with code paths in ways that are rarely tested together. The fallback that handled the no-Unsafe case was almost certainly exercised far less than the mainline path, and it carried a latent address-derivation error that the common configuration never hit. CVE-2026-48040 is a reminder that the rarely-trodden branch — the one that runs only when you have turned a safety feature off in the name of safety — deserves the same scrutiny as the hot path, because attackers will gladly steer you down it.