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 express
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 · 7.5micronaut-http-client Infinite Redirect Loop Denial of Service
- high · 7.5CVE-2026-49477CVE-2026-49477: soupsieve Regular Expression Denial of Service (ReDoS)
- high · 8.1CVE-2026-49464CVE-2026-49464: NL Portal Taak IDOR Allows Takeover of Any User's Open Task
- high · 8CVE-2026-49832CVE-2026-49832: DSpace Remote Code Execution via Velocity Template Injection in LDN