GHSA-8hjv-92q9-g4xj: Micronaut has unbounded `formattersCache` in `TimeConverterRegistrar` that Allows Memory Exhaustion via `Accept-Language` Header
Summary
TimeConverterRegistrar caches DateTimeFormatter instances in an unbounded ConcurrentHashMap<String, DateTimeFormatter> whose key is derived from the @Format annotation pattern concatenated with the locale from the HTTP Accept-Language header. Because Locale.forLanguageTag() accepts arbitrary BCP 47 private-use extensions (en-x-a001, en-x-a002, …), an unauthenticated attacker can generate an unlimited number of unique cache keys by sending requests with novel locale tags, growing the cache until heap memory is exhausted and the JVM crashes. This is structurally identical to the recently patched GHSA-2hcp-gjrf-7fhc (DefaultHtmlErrorResponseBodyProvider), but TimeConverterRegistrar.formattersCache was not covered by that fix.
Details
The vulnerable cache is declared in context/src/main/java/io/micronaut/runtime/converters/time/TimeConverterRegistrar.java at line 123:
// TimeConverterRegistrar.java:123
private final Map<String, DateTimeFormatter> formattersCache = new ConcurrentHashMap<>();
The getFormatter method at line 434 inserts into this map with no eviction or size limit:
// TimeConverterRegistrar.java:434-443
private DateTimeFormatter getFormatter(String pattern, ConversionContext context) {
var key = pattern + context.getLocale(); // locale from Accept-Language header
var cachedFormatter = formattersCache.get(key);
if (cachedFormatter != null) {
return cachedFormatter;
}
var formatter = DateTimeFormatter.ofPattern(pattern, context.getLocale());
formattersCache.put(key, formatter); // NO SIZE CHECK — unbounded growth
return formatter;
}
The attacker-controlled locale flows into the cache key through this call chain:
1. HTTP header parsed — HttpHeaders.findAcceptLanguage() at http/src/main/java/io/micronaut/http/HttpHeaders.java:766-771 calls Locale.forLanguageTag(part) directly on the raw Accept-Language value:
// HttpHeaders.java:766-771
default Optional<Locale> findAcceptLanguage() {
return findFirst(HttpHeaders.ACCEPT_LANGUAGE)
.map(text -> {
Details
Original advisory: https://github.com/advisories/GHSA-8hjv-92q9-g4xj
Exploitation outlook
EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.
- Low exploitation riskCVE-2026-442410.55% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 42% of all scored CVEs.
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-44241 | coverage & exploitation status | NVD · CVE.org |
More from GitHub Security Advisories
- criticalGHSA-g936-7jqj-mwv8: TSDProxy: Internal proxy auth token forwarded to backend services enables management API …2026-07-10
- highGHSA-fpg8-7664-jc5q: melange: Incomplete package integrity verification allows data section substitution2026-07-10
- mediumGHSA-48rx-c7pg-q66r: Excon does not redact additional sensitive/risky headers when following redirects2026-07-10
- highGHSA-h4g2-xfmw-q2c9: Clauster: Non-loopback deployments can serve the dashboard unauthenticated when auth.enab…2026-07-10
- mediumGHSA-rqq5-2gf9-4w4q: Secure Headers: CSP directive injection via sandbox, plugin_types, and report_to when giv…2026-07-10