HAPI FHIR: SHCParser DEFLATE infinite loop causes denial of serviceGHSA-gq9c-wmrm-5hvr
HIGHFix: hapifhir/org.hl7.fhir.core#2493GHSA-gq9c-wmrm-5hvr is a high-severity (CVSS 7.5) Improper Input Validation vulnerability in ca.uhn.hapi.fhir:org.hl7.fhir.r5. A fix is available for ca.uhn.hapi.fhir:org.hl7.fhir.r5 — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for GHSA-gq9c-wmrm-5hvr.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
ca.uhn.hapi.fhir:org.hl7.fhir.r5☕ca.uhn.hapi.fhir:org.hl7.fhir.validation☕ca.uhn.hapi.fhir:org.hl7.fhir.validation.cliReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Maven packages — download data is not available via public APIs for these ecosystems.
Description
Summary
A malformed Smart Health Card (SHC) JWT with zip: "DEF" and an empty or truncated DEFLATE payload causes SHCParser.inflate() to loop forever. This allows an attacker who can submit SHC content for validation to pin a JVM worker thread indefinitely, causing denial of service.
Details
The vulnerable code is in org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java.
decodeJWT() inflates the JWT payload when the header contains "zip":"DEF":
// SHCParser.java:300-302
if ("DEF".equals(res.header.asString("zip"))) {
payloadJson = inflate(payloadJson);
}
inflate() loops only on !inflater.finished() and does not check inflater.needsInput(), inflater.needsDictionary(), or zero-progress output:
// SHCParser.java:455-468
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
For empty or truncated raw DEFLATE input, Inflater.inflate() returns 0, finished() remains false, and needsInput() becomes true, producing an infinite tight loop. The same unsafe loop pattern also exists in decompress() at SHCParser.java:410-423.
The validator reaches this path during SHC validation and during file-format detection for SHC-looking input (ResourceChecker.java:115-118).
PoC
Compile the project, then run a minimal local harness that calls:
SHCParser.inflate(new byte[0]);
This never returns. Local verification:
timeout 3s java -cp ... VerifyDoSFindings shcHang
echo $?
# 124 = timeout killed the hung process
A JWT PoC uses:
- header: Base64URL(
{"zip":"DEF"}) - payload: empty or truncated raw DEFLATE bytes
- signature: arbitrary
Submit the resulting token as SHC content, for example via a .shc file or content beginning with shc:/ that reaches the validator's SHC detection path.
Impact
This is a denial-of-service vulnerability. A single malformed SHC validation request can consume a worker thread indefinitely. In services that validate uploaded SHC content, a small number of concurrent malformed requests can exhaust all validation workers.
Credits
- Thai Son Dinh from VinSOC Labs (R&D)
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| ☕Maven | ca.uhn.hapi.fhir:org.hl7.fhir.r5 | all versions | 6.9.12ca.uhn.hapi.fhir:org.hl7.fhir.r5:6.9.12 |
| ☕Maven | ca.uhn.hapi.fhir:org.hl7.fhir.validation | all versions | 6.9.12ca.uhn.hapi.fhir:org.hl7.fhir.validation:6.9.12 |
| ☕Maven | ca.uhn.hapi.fhir:org.hl7.fhir.validation.cli | all versions | 6.9.12ca.uhn.hapi.fhir:org.hl7.fhir.validation.cli:6.9.12 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for ca.uhn.hapi.fhir:org.hl7.fhir.r5, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update ca.uhn.hapi.fhir:org.hl7.fhir.r5 to 6.9.12 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-gq9c-wmrm-5hvr is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Frequently Asked Questions
Is GHSA-gq9c-wmrm-5hvr in your dependencies?
Find it across Maven, including transitive dependencies.