Micronaut Framework vulnerable to a Denial of Service in HTML error response caching
Description
Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. Versions 4.7.0 through 4.10.16 used an unbounded ConcurrentHashMap cache with no eviction policy in its DefaultHtmlErrorResponseBodyProvider. If the application throws an exception whose message may be influenced by an attacker, (for example, including request query value parameters) it could be used by remote attackers to cause an unbounded heap growth and OutOfMemoryError, leading to DoS. This issue has been fixed in version 4.10.7.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Micronaut Framework 4.7.0–4.10.16 uses an unbounded cache in DefaultHtmlErrorResponseBodyProvider, allowing remote DoS via attacker-controlled exception messages.
Vulnerability
CVE-2026-33012 affects Micronaut Framework versions 4.7.0 through 4.10.16. The DefaultHtmlErrorResponseBodyProvider uses an unbounded ConcurrentHashMap cache with no eviction policy. policy. When an application throws an exception whose message can be influenced by an attacker (e.g., via request query parameters), each unique message is cached indefinitely, leading to unbounded heap growth and an OutOfMemoryError [1].
Exploitation
An attacker can send crafted requests that cause the application to generate exception messages containing attacker-controlled content. Because the cache key is derived from the exception message, each distinct message creates a new cache entry. No authentication is required; the attack is performed over the network by sending HTTP requests to the vulnerable endpoint [1].
Impact
Successful exploitation results in a denial of service (DoS) due to memory exhaustion. The application may crash or become unresponsive, affecting availability. The vulnerability does not require any special privileges or user interaction beyond sending malicious requests [1].
Mitigation
The issue is fixed in Micronaut Core version 4.10.7. The fix replaces the unbounded ConcurrentHashMap with a synchronizedMap that enforces a maximum cache size, preventing unbounded growth [2]. Users should upgrade to 4.10.7 or later. No workarounds are documented.
AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
io.micronaut:micronaut-http-serverMaven | >= 4.7.0, < 4.10.17 | 4.10.17 |
Affected products
2- Range: >=4.7.0, <=4.10.16
- micronaut-projects/micronaut-corev5Range: >= 4.7.0, < 4.10.17
Patches
11e2ba2c14386Replace ConcurrentHashMap with synchronizedMap
2 files changed · +96 −2
http-server/src/main/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProvider.java+10 −2 modified@@ -21,6 +21,7 @@ import io.micronaut.core.annotation.NonNull; import io.micronaut.core.util.LocaleResolver; import io.micronaut.core.util.StringUtils; +import io.micronaut.core.util.clhm.ConcurrentLinkedHashMap; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; @@ -32,7 +33,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import static io.micronaut.http.HttpStatus.*; @@ -128,10 +128,14 @@ final class DefaultHtmlErrorResponseBodyProvider implements HtmlErrorResponseBod } """; + private static final int MAX_CACHE_SIZE = 100; + private final HtmlSanitizer htmlSanitizer; private final MessageSource messageSource; private final LocaleResolver<HttpRequest<?>> localeResolver; - private final Map<HtmlErrorPage, String> cache = new ConcurrentHashMap<>(); + private final Map<HtmlErrorPage, String> cache = new ConcurrentLinkedHashMap.Builder<HtmlErrorPage, String>() + .maximumWeightedCapacity(MAX_CACHE_SIZE) + .build(); DefaultHtmlErrorResponseBodyProvider(HtmlSanitizer htmlSanitizer, MessageSource messageSource, @@ -217,4 +221,8 @@ private record HtmlErrorPage(Locale locale, String errorBold, List<String> messages) { } + + Map<HtmlErrorPage, String> getCache() { + return cache; + } }
test-suite/src/test/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProviderCacheMaxSizeTest.java+86 −0 added@@ -0,0 +1,86 @@ +package io.micronaut.http.server.exceptions.response; + +import io.micronaut.context.annotation.Property; +import io.micronaut.context.annotation.Requires; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.HttpStatus; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Post; +import io.micronaut.http.annotation.Produces; +import io.micronaut.http.annotation.Status; +import io.micronaut.http.client.BlockingHttpClient; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.client.exceptions.HttpClientResponseException; +import io.micronaut.http.uri.UriBuilder; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Property(name = "spec.name", value = "DefaultHtmlErrorResponseBodyProviderCacheMaxSize") +@MicronautTest +class DefaultHtmlErrorResponseBodyProviderCacheMaxSizeTest { + + @Test + void errorResponseCacheHasAMaxSize(@Client("/") HttpClient httpClient, + DefaultHtmlErrorResponseBodyProvider defaultHtmlErrorResponseBodyProvider) { + BlockingHttpClient client = httpClient.toBlocking(); + int max = 10; + for (int i = 1; i <= max; i++) { + URI uri = UriBuilder.of("/errorcache").queryParam("nonce", String.valueOf(i)).build(); + HttpRequest<?> request = HttpRequest.POST(uri, Collections.emptyMap()) + .accept(MediaType.TEXT_HTML); + HttpClientResponseException ex = assertThrows(HttpClientResponseException.class, () -> client.exchange(request)); + assertEquals(HttpStatus.NOT_ACCEPTABLE, ex.getStatus()); + } + assertEquals(1, defaultHtmlErrorResponseBodyProvider.getCache().size()); + } + + @Test + void errorResponseCacheHasAMaxSizeForCustomException(@Client("/") HttpClient httpClient, + DefaultHtmlErrorResponseBodyProvider defaultHtmlErrorResponseBodyProvider) { + BlockingHttpClient client = httpClient.toBlocking(); + int size = 110; + int max = 100; + assertTrue(max < size); + for (int i = 1; i <= size; i++) { + URI uri = UriBuilder.of("/errorcache").path("/ex").queryParam("nonce", String.valueOf(i)).build(); + HttpRequest<?> request = HttpRequest.POST(uri, Collections.emptyMap()) + .accept(MediaType.TEXT_HTML); + HttpClientResponseException ex = assertThrows(HttpClientResponseException.class, () -> client.exchange(request)); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, ex.getStatus()); + } + assertEquals(max, defaultHtmlErrorResponseBodyProvider.getCache().size()); + } + + @Requires(property = "spec.name", value = "DefaultHtmlErrorResponseBodyProviderCacheMaxSize") + @Controller("/errorcache") + static class OnlyPostController { + @Produces(MediaType.TEXT_PLAIN) + @Status(HttpStatus.OK) + @Post + void index() { + } + + @Produces(MediaType.TEXT_HTML) + @Post("/ex") + @Status(HttpStatus.OK) + void ex(HttpRequest<?> request) { + throw new CustomException(request); + } + } + + static class CustomException extends RuntimeException { + CustomException(HttpRequest<?> request) { + super("foobar "+ request.getUri()); + } + } + +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-2hcp-gjrf-7fhcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-33012ghsaADVISORY
- github.com/micronaut-projects/micronaut-core/commit/1e2ba2c14386af3d47751732d02053a72b0b49b3ghsax_refsource_MISCWEB
- github.com/micronaut-projects/micronaut-core/releases/tag/v4.10.17ghsax_refsource_MISCWEB
- github.com/micronaut-projects/micronaut-core/security/advisories/GHSA-2hcp-gjrf-7fhcghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.