Micronaut has Unbounded `bundleCache` in `ResourceBundleMessageSource` that Allows Memory Exhaustion via `Accept-Language` Header
Date: 2026-05
Affected: maven/io.micronaut:micronaut-inject, maven/io.micronaut:micronaut-inject, maven/io.micronaut:micronaut-inject
Attack vector: dos
Category: vulnerability-disclosure
Severity: Low
CVE: CVE-2026-44242
CWE: CWE-400
CVSS: 3.7 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L)

## Summary `ResourceBundleMessageSource` maintains two caches: `messageCache` (bounded at 100 entries via `ConcurrentLinkedHashMap`) and `bundleCache` (unbounded `ConcurrentHashMap`). The `bundleCache` is keyed by `(Locale, baseName)` where the locale originates from the HTTP `Accept-Language` header. In applications that explicitly register a `ResourceBundleMessageSource` bean and serve HTML error responses, an unauthenticated attacker can exhaust heap memory by sending requests with large numbers of unique `Accept-Language` values, each causing a new entry in the unbounded `bundleCache`. Unlike GHSA-2hcp-gjrf-7fhc and the sibling `messageCache` (both bounded), `bundleCache` was not updated to use a bounded cache implementation. ## Details The `bundleCache` is initialized in `inject/src/main/java/io/micronaut/context/i18n/ResourceBundleMessageSource.java` at line 150: ```java // ResourceBundleMessageSource.java:139-152 protected Map<MessageKey, Optional<String>> buildMessageCache() { return new ConcurrentLinkedHashMap.Builder<MessageKey, Optional<String>>() .maximumWeightedCapacity(100) // ← BOUNDED ✓ .build(); } protected Map<MessageKey, Optional<ResourceBundle>> buildBundleCache() { return new ConcurrentHashMap<>(18); // ← UNBOUNDED ✗ } ``` The `resolveBundle()` method at line 169 inserts into `bundleCache` with no eviction policy: ```java // ResourceBundleMessageSource.java:169-185 private Optional<ResourceBundle> resolveBund


Mitigations:

Architectural layers (MAESTRO):