HAPI FHIR: SHCParser unbounded DEFLATE decompression causes denial of serviceGHSA-3w98-rrpr-fprr
HIGHFix: hapifhir/org.hl7.fhir.core#2493GHSA-3w98-rrpr-fprr 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-3w98-rrpr-fprr.
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
SHCParser inflates compressed Smart Health Card JWT payloads into memory without a decompressed-size limit. An attacker who can submit SHC content for validation can craft a small compressed JWT payload that expands to a very large byte array, causing memory exhaustion or severe garbage collection pressure.
Details
The vulnerable code is in org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/SHCParser.java.
decodeJWT() checks MAX_ALLOWED_SHC_LENGTH, but this only logs an error and parsing continues:
// SHCParser.java:282-284
if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) {
logError(...);
}
If the header contains "zip":"DEF", the payload is inflated before JSON parsing:
// SHCParser.java:300-304
if ("DEF".equals(res.header.asString("zip"))) {
payloadJson = inflate(payloadJson);
}
res.payload = JsonParser.parseObject(FileUtilities.bytesToString(payloadJson), true);
inflate() accumulates all decompressed output in a ByteArrayOutputStream and has no maximum output size:
// SHCParser.java:455-468
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
return outputStream.toByteArray();
The same unbounded decompression pattern exists in decompress() at SHCParser.java:410-423.
PoC
Create a highly compressible SHC-shaped JSON payload, compress it with raw DEFLATE (new Deflater(9, true)), Base64URL-encode it as the JWT payload, and set the JWT header to {"zip":"DEF"}.
Local verification measured the following expansion through SHCParser.inflate():
plain=1000066 compressed=1052 inflated=1000066 ratio=950
plain=16000066 compressed=15626 inflated=16000066 ratio=1023
A small compressed payload can therefore allocate many megabytes of heap. Larger payloads can trigger OutOfMemoryError or process instability.
Impact
This is a denial-of-service vulnerability. Any validator service or application that accepts attacker-supplied SHC content can be forced to allocate excessive heap memory. Impact ranges from request failure and severe GC pressure to process termination.
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 | No fix |
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-3w98-rrpr-fprr 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-3w98-rrpr-fprr in your dependencies?
Find it across Maven, including transitive dependencies.