AsyncHttpClient CVE-2026-107282: when a replayed request carries the wrong identity
The failure class, not just the identifier
CVE-2026-107282 is one entry in a batch of fixes published for AsyncHttpClient (AHC), the Java library that a large share of JVM services use to make outbound HTTP calls. The batch matters more than any single item because every entry in it has the same shape: the client decides who it is, or who it is talking to, from state that was computed for a different request. The result is a library that is diligent about authentication and still sends credentials to the wrong place.
The headline issue, affecting versions before 3.0.13 and 2.16.1, concerns cross-host request replay. When AHC re-issues a request against a different host, it updates the current request object but leaves the target request and the associated proxy context pointing at the original host. Path, Host header, Authorization credentials, or a cleartext body computed for host A can therefore be transmitted to host B.
Why that is a credential disclosure rather than a cosmetic bug
Consider a service that talks to an internal API and, after a redirect or a retry against a different endpoint, replays a request. The Authorization header was minted for the first host. The second host may be a third-party service, a different tenant's endpoint, or an attacker-controlled redirect target. Because the client decided the request was a replay, from its point of view nothing unusual happened; from the receiving end, a valid bearer token for an unrelated system just arrived in plaintext or in a header the receiver can read.
The same reasoning applies to the body. A replayed POST whose payload was assembled for the original destination can carry internal identifiers, query fragments or credentials to a host that was never meant to see them. In a microservice mesh where dozens of internal services trust bearer tokens issued by a shared issuer, a single misplaced header is enough to move laterally.
The practical lesson is about the object model, not about HTTP. Replay is inherently a copy operation, and every field of the copy has to be re-derived for the new destination. When one field is treated as immutable context, the copy is incomplete, and the incompleteness is invisible to any test that only checks whether the retry succeeded.
The rest of the batch
CVE-2026-107281 is arguably the more interesting sibling. The HTTP/1.1 connection pool key excludes the authenticated principal when connection-oriented NTLM or Negotiate authentication is in use, in versions before 3.0.13 and 2.16.1. A pooled connection that was established under one identity can therefore be handed to a different identity. Connection reuse is the entire point of a pool, and NTLM authenticates the connection rather than each request, so the substitution is not visible at the request layer. Any multi-tenant service that authenticates to a downstream system with NTLM through a shared client instance is exposed, and the failure is silent on both ends.
CVE-2026-107283, rated Low, is a cryptographic hygiene defect: Realm.Builder generates the HTTP Digest client nonce with ThreadLocalRandom rather than a cryptographically secure source, in versions before 3.0.12 and 2.16.1. A predictable nonce weakens the replay protection that Digest was designed to provide, which makes an unrelated credential-exposure bug worse rather than better.
CVE-2026-107284, also Low, concerns WebSocketHandler.upgrade: a handshake whose Sec-WebSocket-Accept value is missing or invalid is aborted, but the handler continues into pipeline installation. Failing to stop on a failed validation is exactly the pattern that turns a validation routine into a formality.
CVE-2026-107285, Medium at 5.9, involves proxy authentication on WebSocket requests tunnelled through CONNECT, where NettyRequestFactory.newNettyRequest and requestUri decide whether to attach proxy credentials, in versions before 3.0.12 and 2.16.1. The details differ from the cross-host replay case, the reasoning does not: a decision about credentials is made from context that does not describe the request actually being sent.
A related defect in a different Java client shows how common the shape is. CVE-2026-107314 describes pgjdbc, the PostgreSQL JDBC driver, in versions 42.7.11 through 42.7.13: when the requireAuth connection property excludes every authentication method the driver knows, for example by listing them all with negation, the driver enforces nothing and accepts any method the server offers. A configuration intended to restrict authentication produces no restriction at all. The score is 5.9 and the consequence is a downgrade to whatever the server proposes.
What to do
Upgrade. The AHC fixes are in 3.0.13 and 2.16.1 for the replay and pool-key issues, and in 3.0.12 and 2.16.1 for the proxy and WebSocket items, so the practical target is the newest build in the line you maintain. Because the library is a transitive dependency in most projects, the version that matters is the one resolved into the final artifact, not the one you typed.
Inventories should be resolved dependency trees, not dependency files. Ask the build for the effective version of org.asynchttpclient:async-http-client in every deployable, and rerun the query after a framework upgrade, because spring and cloud libraries routinely pin the version for you.
If NTLM or Negotiate authentication to a downstream system is in play, treat CVE-2026-107281 as the priority. It is the item that can cross an identity boundary inside your own infrastructure without any external redirect, and it will not appear in a request log that only records that a 200 was returned.
Review your own use of copies. Where your code builds a request for one destination and then reuses it for another, verify that the URI, Host header, credentials and body are all recomputed. The library fix closes the library's path; application-level copies have the same failure mode.
Rotate where exposure was possible. Any deployment that ran an affected version between the release of the fix and the upgrade may have delivered a credential to a host that should never have received it, and rotating is cheaper than reasoning about whether it did.
Top comments (0)