Jul 9, 2026·6 min read·18 visits
A missing ceiling on HTTP redirections in Micronaut's Netty HTTP Client allows a remote server to trap the client in an infinite loop, causing severe Denial of Service through thread and resource starvation.
The Netty-based HTTP Client in the Micronaut framework fails to enforce a maximum redirect ceiling by default when processing HTTP responses. This permits remote, attacker-controlled servers to trigger continuous, infinite redirect loops. The resulting recursion causes high CPU utilization, thread starvation, and potential memory exhaustion, inducing a Denial of Service (DoS) state in client-side applications.
The Micronaut HTTP Client is an asynchronous, reactive HTTP client built on top of the Netty event-driven network application framework. It is a core module in the Micronaut ecosystem, facilitating asynchronous service-to-service communication, metadata fetching, and API aggregation. By default, the client is configured to automatically follow HTTP 3xx redirection responses.
This vulnerability stems from a lack of state tracking in the client's redirection logic. Prior to the fix, the client parsed incoming Location headers and recursively initiated subsequent connections without keeping track of the total redirection depth. If a destination target resolves to a looping sequence, the client follows the route indefinitely.
Because the HTTP Client handles asynchronous, reactive streams via underlying Netty EventLoop groups, entering an endless redirect loop exhausts critical system resources. This attack surface is exposed whenever a Micronaut client fetches data from an endpoint controlled or influenced by an untrusted party, leading directly to a complete Denial of Service on the host application.
The root cause of GHSA-387m-935m-c4vw lies in the redirection resolution path of DefaultHttpClient and NettyHttpClient. When automatic redirect tracking is active (followRedirects = true), receiving an HTTP 3xx status code triggers the extraction of the target URI from the Location response header. The state machine then builds a secondary client request and subscribes to its response flow.
In vulnerable versions, the state machine did not keep any execution-context tracking or counter variables across these consecutive request hops. There was no boundary condition checking the accumulation of redirects. Consequently, when a loop occurs, the reactive pipeline continues to allocate execution frames, schedule channel operations, and spawn TCP sockets indefinitely.
This continuous execution sequence causes three distinct failure modes on the client host. First, the system experiences CPU exhaustion as the CPU cores dedicated to Netty's reactive event loops are driven to full capacity processing HTTP frames. Second, ephemeral port allocations and file descriptors are quickly consumed by active, unclosed connections. Lastly, the creation of sequential connection contexts and reactive stream subscribers puts high pressure on the JVM garbage collector, occasionally causing OutOfMemoryError states under concurrent conditions.
The vulnerability was mitigated across the Micronaut 3, 4, and 5 branches by adding a state-tracking attribute to the request lifecycle. The implementation adds a configuration property DEFAULT_MAX_REDIRECTS set to five, which represents the default ceiling for redirection paths. This value is configurable via the micronaut.http.client.max-redirects configuration namespace.
An attribute string micronaut.http.client.redirect-count was introduced to carry the current recursion level through the request execution context. During redirection, the client reads this value, verifies it against the configured threshold, increments it, and updates the subsequent request attributes.
Reviewing the official patch in the Netty client implementation demonstrates how this logic was integrated into the reactive flow:
// In DefaultHttpClient.java / NettyHttpClient.java
private static final String REDIRECT_COUNT = "micronaut.http.client.redirect-count";
// Redirection logic verification block:
int redirectCount = request.getAttribute(REDIRECT_COUNT, Integer.class).orElse(0) + 1;
if (redirectCount > configuration.getMaxRedirects()) {
return ExecutionFlow.error(decorate(new HttpClientException("Maximum number of redirects exceeded at redirect count: " + redirectCount)));
}
redirectRequest.setAttribute(REDIRECT_COUNT, redirectCount);If the integer counter exceeds the configured redirect ceiling, the execution flow is broken immediately by returning an HttpClientException wrapped in an error block. This immediately halts the reactive pipeline, preventing further network socket allocation and releasing event loop resources. The fix is considered structurally complete because it utilizes context-propagating request attributes, ensuring safety even in non-blocking, multi-threaded reactive execution paths.
Exploitation of GHSA-387m-935m-c4vw is straightforward and requires no prior credentials. The attack is feasible against any endpoint of a Micronaut application that accepts a user-defined URL and uses the default HTTP Client configuration to retrieve content from that URL. Common examples include metadata extractors, web scrapers, proxy components, and webhook handlers.
An attacker begins by deploying an HTTP server on a public domain. This malicious server is configured to return redirect headers pointing recursively to itself or another loop location. For instance, the server returns a 302 Found response with a Location: /loop header, where /loop subsequently redirects back to /loop.
When the victim Micronaut application processes the initial URL, it queries the attacker's server, parses the Location header, and automatically schedules another connection. Because there is no check on redirect depth, the client repeatedly generates requests. If an attacker submits several looping URLs concurrently, the client's entire pool of Netty execution threads is bound to the loop, causing the application to become unresponsive to legitimate client traffic.
The threat of this vulnerability is confined to availability, carrying a CVSS v3.1 base score of 7.5. Because the vulnerability only resides in the client execution flow, it does not allow for unauthorized access, data extraction, or remote privilege escalation. Confidentiality and Integrity are unaffected.
However, the availability impact is high. In systems running cloud microservice architectures, thread starvation inside one Micronaut application can quickly cascade. If the microservice hosts critical authentication middleware or acts as an API gateway, the resulting thread pool exhaustion can take down dependent systems.
Because the flaw consumes resources directly proportional to concurrent loops, it acts as an effective, low-complexity vector for Distributed Denial of Service (DDoS) amplification. An attacker only needs to send a single request containing a looping URL to initiate a long-lived resource exhaustion process on the victim application.
To fully remediate the issue, users must upgrade their Micronaut framework or HTTP Client dependencies to a patched version. For applications running on Micronaut 3, update to version 3.10.7 or higher. For Micronaut 4 applications, migrate to version 4.10.24 or higher, and for Micronaut 5 applications, update to version 5.0.1 or higher.
In circumstances where library upgrades cannot be immediately applied, developers can mitigate the risk by modifying the application's configuration file (application.yml). Setting the automatic redirection property to false prevents the client from following any redirects:
micronaut:
http:
client:
follow-redirects: falseIf automatic redirects are disabled, applications that require redirection support must implement manual location checking. By reading the Location header programmatically, the application can validate the target domain, verify that the URI matches a strict whitelist, and discard requests that exhibit cyclic behavior. Egress network filtering should also be applied to prevent microservices from communicating with untrusted external destinations.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
micronaut-http-client Micronaut | < 3.10.7 | 3.10.7 |
micronaut-http-client Micronaut | >= 4.0.0-M1, < 4.10.24 | 4.10.24 |
micronaut-http-client Micronaut | >= 5.0.0-M1, < 5.0.1 | 5.0.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-835 |
| Attack Vector | Network |
| CVSS v3.1 | 7.5 |
| Impact | Denial of Service (Availability: High) |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The program contains an iteration or loop with an exit condition that cannot be reached or is not met, causing the program to loop indefinitely.
Grav CMS prior to version 1.7.53 and 2.0.0-rc.8 is vulnerable to an unauthenticated remote denial of service (DoS) vulnerability. By supplying crafted query parameters with extremely large dimensions to image assets, remote unauthenticated attackers can force the server to allocate massive amounts of system memory, leading to kernel Out-Of-Memory (OOM) termination of web worker processes.
CVE-2026-53657 is a local privilege escalation vulnerability in Lima (lima-vm/lima) affecting versions prior to 2.1.3 when configured with the QEMU driver. The guest agent daemon, running as root, creates its communication socket `/run/lima-guestagent.sock` with world-writable permissions (0777). This allows unprivileged local users to command the agent to establish arbitrary tunnels, including to privileged local UNIX sockets (like D-Bus). Because the target daemon authenticates the incoming connection using the credentials of the root-owned guest agent (via SO_PEERCRED), unprivileged users can perform root operations, resulting in complete guest VM compromise.
An unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.
A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.
SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.