rpcs3 (4, C++), ppsspp (4, C++), spring-framework (3, Java), nats-server (3, Go), minio (3, Go), gimp (3, C), cockroach (3, Go), superset (3, Python). Note: rpcs3-0004 is CWE-312, rest are CWE-407.
5.6 KiB
Spring Framework — CWE-407 Disclosure Brief
2026-04-13 · Patches available — awaiting upstream merge
Finding
Three O(n²) defects in Spring Framework across CORS header validation, locale resolution, and static resource encoding negotiation. All patched. Patches ready for upstream review. All three defects fire on every HTTP request that hits the affected path.
The Defects
spring-framework-0001 (PATCHED — HIGH): spring-web/.../CorsConfiguration.java:724
// In checkHeaders() — fires per CORS preflight/actual request:
for (String allowedHeader : this.allowedHeaders) {
if (requestHeader.equalsIgnoreCase(allowedHeader)) {
result.add(requestHeader);
break;
}
}
allowedHeaders stores permitted CORS headers as an ArrayList. checkHeaders() iterates request headers (R) and for each scans the entire allowed headers list (A) with case-insensitive comparison. Total: O(R×A) per request. Fires on every CORS-enabled endpoint.
spring-framework-0002 (PATCHED — MEDIUM): spring-webmvc/.../AcceptHeaderLocaleResolver.java:103 and spring-web/.../AcceptHeaderLocaleContextResolver.java:114
// In findSupportedLocale() — fires per request with Accept-Language header:
if (supportedLocales.contains(locale)) {
// ...
}
supportedLocales stores configured locales as an ArrayList. contains() does O(S) linear scan for every request locale from the Accept-Language header. Total: O(R×S) per request. Present in both the servlet and reactive WebFlux variants.
spring-framework-0003 (PATCHED — MEDIUM): spring-webmvc/.../EncodedResourceResolver.java:66 and spring-webflux/.../EncodedResourceResolver.java:67
// In resolveResource() — fires per static resource request:
private final List<String> contentCodings = new ArrayList<>(DEFAULT_CODINGS);
// ... later, per accepted encoding:
if (contentCodings.contains(coding)) { ... }
contentCodings stores supported compression encodings (br, gzip) as an ArrayList. For each Accept-Encoding token in the request, contains() scans the list — O(A×C) per static resource request. Present in both servlet and reactive variants.
Complexity Proof
spring-framework-0001: At R=20 request headers, A=30 allowed headers:
- Defective: 20 × 30 = 600 case-insensitive comparisons per request
- Fixed: 20 × 1 = 20 set lookups (LinkedHashSet)
- 30× op reduction per request. At 10,000 req/s = 6,000,000 → 200,000 comparisons/s.
spring-framework-0002: At R=10 Accept-Language locales, S=20 supported locales:
- Defective: 10 × 20 = 200 comparisons per request
- Fixed: 10 × 1 = 10 set lookups (LinkedHashSet)
- 20× op reduction per request.
spring-framework-0003: At A=5 accepted encodings, C=3 content codings:
- Defective: 5 × 3 = 15 comparisons per request
- Fixed: 5 × 1 = 5 set lookups (LinkedHashSet)
- 3× op reduction per request. Lower ratio but fires on every static resource request.
Impact
Spring Framework powers millions of Java web applications worldwide — the dominant server-side Java framework. spring-framework-0001 fires on every CORS-enabled endpoint, which includes most modern APIs serving browser clients. At scale (thousands of requests per second with many allowed headers), the quadratic scan consumes measurable CPU. spring-framework-0002 fires on every request with an Accept-Language header when locale resolution uses the default AcceptHeaderLocaleResolver — virtually every internationalized application. spring-framework-0003 fires on every static resource request when content encoding negotiation activates.
The Fix
spring-framework-0001: Build a LinkedHashSet<String> (case-folded to lowercase) from allowedHeaders at the start of checkHeaders(). Replace the inner loop with a single allowedSet.contains(requestHeader.toLowerCase()) call.
// Before
for (String allowedHeader : this.allowedHeaders) {
if (requestHeader.equalsIgnoreCase(allowedHeader)) { ... }
}
// After — O(1) per header
Set<String> allowedSet = new LinkedHashSet<>();
for (String h : this.allowedHeaders) {
allowedSet.add(h.toLowerCase(Locale.ROOT));
}
if (allowedSet.contains(requestHeader.toLowerCase(Locale.ROOT))) { ... }
spring-framework-0002: Maintain a LinkedHashSet<Locale> alongside the supportedLocales list. Replace supportedLocales.contains(locale) with supportedSet.contains(locale).
spring-framework-0003: Change contentCodings from ArrayList to LinkedHashSet for O(1) contains().
Patch
Fixes available:
defects/spring-framework/patch/spring-framework-0001-cors-check-headers-o-r-a.patchdefects/spring-framework/patch/spring-framework-0002-accept-language-locale-o-r-s.patchdefects/spring-framework/patch/spring-framework-0003-encoded-resource-resolver-content-codings-o-a-c.patch
Three patches across CorsConfiguration.java, AcceptHeaderLocaleResolver.java, AcceptHeaderLocaleContextResolver.java, and EncodedResourceResolver.java (both servlet and reactive variants).
What We Ask
Patches ready for review.
- Confirm receipt and assign a GitHub issue reference (spring-projects/spring-framework).
- Assess severity — spring-framework-0001 fires on every CORS request; spring-framework-0002 fires on every localized request; spring-framework-0003 fires on every encoded static resource request.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the Spring team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.