GHSA-3w98-rrpr-fprr: Input Validation
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 MAXALLOWEDSHCLENGTH, but this only logs an error and parsing continues:
java // SHCParser.java:282-284 if (jwt.length() > MAXALLOWEDSHCLENGTH) { logError(...); }
If the header contains "zip":"DEF", the payload is inflated before JSON parsing:
java // 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:
java // 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():
text 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 Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
maven/ca.uhn.hapi.fhir:org.hl7.fhir.validationto a version that resolves this vulnerability.Fixed in 6.9.12 - Upgrade
Upgrade
maven/ca.uhn.hapi.fhir:org.hl7.fhir.r5to a version that resolves this vulnerability.Fixed in 6.9.12
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Deployments using the listed org.hl7.fhir.r5, org.hl7.fhir.validation, or org.hl7.fhir.validation.cli Maven artifacts are in scope when they accept Smart Health Card content for validation.
What must an attacker provide to trigger the memory-exhaustion condition?
An attacker needs to submit a Smart Health Card JWT whose header specifies "zip":"DEF" and whose compressed payload expands to a very large size when inflated. No authentication or user interaction is indicated by the provided severity vector.
Does the existing Smart Health Card length check prevent exploitation?
No. MAX_ALLOWED_SHC_LENGTH only causes an error to be logged when the JWT exceeds the limit; parsing continues and the compressed payload can still be inflated without a decompressed-size limit.