Every CVE Search/ Get API key

CVE-2026-44241

Micronaut Framework: Unbounded formattersCache in TimeConverterRegistrar Allows Memory Exhaustion via Accept-Language Header

7.5 HighFix available

Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. From 4.3.0 to before 4.10.22, 3.10.6, and 3.8.14, 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 vulnerability is fixed in 4.10.22, 3.10.6, and 3.8.14.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.64%Up 0.6 points since May 13, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

Micronaut Framework: Unbounded formattersCache in TimeConverterRegistrar Allows Memory Exhaustion via Accept-Language Header

Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. From 4.3.0 to before 4.10.22, 3.10.6, and 3.8.14, 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 vulnerability is fixed in 4.10.22, 3.10.6, and 3.8.14.

Record
CVE-2026-44241
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
EUVDEUVD-2026-29860 7.5

Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. From 4.3.0 to before 4.10.22, 3.10.6, and 3.8.14, 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 vulnerability is fixed in 4.10.22, 3.10.6, and 3.8.14.

Record
EUVD-2026-29860
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-8hjv-92q9-g4xj 7.5

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 -> {
            String part = HttpHeadersUtil.splitAcceptHeader(text);
            return part == null ? Locale.getDefault() : Locale.forLanguageTag(part);
        });
}
  1. Locale planted in ConversionContext — AbstractRouteMatch.newContext() at router/src/main/java/io/micronaut/web/router/AbstractRouteMatch.java:373-378 passes the request locale into the conversion context for every route argument binding:
// AbstractRouteMatch.java:373-378
private <E> ArgumentConversionContext<E> newContext(Argument<E> argument, HttpRequest<?> request) {
    return ConversionContext.of(
        argument,
        request.getLocale().orElse(null),   // ← attacker-controlled via Accept-Language
        request.getCharacterEncoding()
    );
}
  1. Unbounded cache insert — When any temporal argument annotated with @Format is bound, TimeConverterRegistrar.getFormatter(pattern, context) is called and inserts a new DateTimeFormatter for each unique pattern + locale key.

This path is triggered for any route endpoint with a @Format-annotated temporal parameter. This is an officially documented and commonly used Micronaut pattern, demonstrated in the framework's own test suite:

// test-suite/.../BindingController.java:105 (official Micronaut example)
@Get("/dateFormat")
public String dateFormat(@Format("dd/MM/yyyy hh:mm:ss a z") @Header ZonedDateTime date) {
    return date.toString();
}

TimeConverterRegistrar is an @Internal core bean registered unconditionally in every Micronaut application — it is not optional or user-configured. By contrast, the DefaultHtmlErrorResponseBodyProvider cache patched in GHSA-2hcp-gjrf-7fhc now uses a ConcurrentLinkedHashMap bounded at 100 entries; TimeConverterRegistrar.formattersCache remains an unbounded plain ConcurrentHashMap.

PoC

…

Record
GHSA-8hjv-92q9-g4xj
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
NVD 7.5

Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. From 4.3.0 to before 4.10.22, 3.10.6, and 3.8.14, 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 vulnerability is fixed in 4.10.22, 3.10.6, and 3.8.14.

Record
CVE-2026-44241
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
OSV 7.5

Micronaut Framework: Unbounded formattersCache in TimeConverterRegistrar Allows Memory Exhaustion via Accept-Language Header

Micronaut Framework is a JVM-based full stack Java framework designed for building modular, easily testable JVM applications. From 4.3.0 to before 4.10.22, 3.10.6, and 3.8.14, 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 vulnerability is fixed in 4.10.22, 3.10.6, and 3.8.14.

Record
CVE-2026-44241
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02
OSVGHSA-8hjv-92q9-g4xj 7.5

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 -> {
            String part = HttpHeadersUtil.splitAcceptHeader(text);
            return part == null ? Locale.getDefault() : Locale.forLanguageTag(part);
        });
}
  1. Locale planted in ConversionContext — AbstractRouteMatch.newContext() at router/src/main/java/io/micronaut/web/router/AbstractRouteMatch.java:373-378 passes the request locale into the conversion context for every route argument binding:
// AbstractRouteMatch.java:373-378
private <E> ArgumentConversionContext<E> newContext(Argument<E> argument, HttpRequest<?> request) {
    return ConversionContext.of(
        argument,
        request.getLocale().orElse(null),   // ← attacker-controlled via Accept-Language
        request.getCharacterEncoding()
    );
}
  1. Unbounded cache insert — When any temporal argument annotated with @Format is bound, TimeConverterRegistrar.getFormatter(pattern, context) is called and inserts a new DateTimeFormatter for each unique pattern + locale key.

This path is triggered for any route endpoint with a @Format-annotated temporal parameter. This is an officially documented and commonly used Micronaut pattern, demonstrated in the framework's own test suite:

// test-suite/.../BindingController.java:105 (official Micronaut example)
@Get("/dateFormat")
public String dateFormat(@Format("dd/MM/yyyy hh:mm:ss a z") @Header ZonedDateTime date) {
    return date.toString();
}

TimeConverterRegistrar is an @Internal core bean registered unconditionally in every Micronaut application — it is not optional or user-configured. By contrast, the DefaultHtmlErrorResponseBodyProvider cache patched in GHSA-2hcp-gjrf-7fhc now uses a ConcurrentLinkedHashMap bounded at 100 entries; TimeConverterRegistrar.formattersCache remains an unbounded plain ConcurrentHashMap.

PoC

…

Record
GHSA-8hjv-92q9-g4xj
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
io.micronaut:micronaut-context
Maven
4.3.0 up to 4.10.22
4.10.22
io.micronaut:micronaut-context
Maven
3.10.0 up to 3.10.6
3.10.6
io.micronaut:micronaut-context
Maven
before 3.8.14
3.8.14
io.micronaut:micronaut-context
Maven
4.3.0 up to 4.10.22, plus listed versions
4.10.04.10.14.10.104.10.114.10.12
Show 45 moreShow less
4.10.134.10.144.10.154.10.164.10.174.10.184.10.194.10.24.10.204.10.214.10.34.10.44.10.54.10.64.10.74.10.84.10.94.3.14.3.104.3.114.3.124.3.134.3.144.3.154.3.164.3.174.3.24.3.34.3.44.3.54.3.64.3.74.3.84.3.94.4.04.4.14.4.104.4.24.4.34.4.44.4.54.4.64.4.74.4.84.4.9
4.10.22
io.micronaut:micronaut-context
Maven
3.10.0 up to 3.10.6, plus listed versions
3.10.13.10.23.10.33.10.43.10.5
3.10.6
io.micronaut:micronaut-context
Maven
before 3.8.14, plus listed versions
2.4.02.4.12.4.22.4.32.4.4
Show 45 moreShow less
2.5.02.5.12.5.102.5.112.5.122.5.132.5.22.5.32.5.42.5.52.5.62.5.72.5.82.5.93.0.03.0.0-M13.0.0-M23.0.0-M33.0.0-M43.0.0-M53.0.0-RC13.0.13.0.23.0.33.1.03.1.13.1.23.1.33.1.43.2.03.2.13.2.23.2.33.2.43.2.53.2.63.2.73.3.03.3.0-M13.3.13.3.23.3.33.3.43.4.03.4.1
3.8.14

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-44241 is a high vulnerability (CVSS 7.5) in Micronaut-projects Micronaut-core, published May 6, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.64%, the 50th percentile. Fixed in io.micronaut:micronaut-context 4.10.22.

References

Show 5 moreShow less
This page doesn't list everything

Left out here: 115 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open