GHSA-gq9c-wmrm-5hvr: Input Validation

Published Sep 17, 2026
·
Updated

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":

java // 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:

java // 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:

java SHCParser.inflate(new byte[0]);

This never returns. Local verification:

bash 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 Software

3 affected componentsFixes available
maven/ca.uhn.hapi.fhir:org.hl7.fhir.validation.cli<=6.9.11
6.9.12
maven/ca.uhn.hapi.fhir:org.hl7.fhir.validation<=6.9.11
6.9.12
maven/ca.uhn.hapi.fhir:org.hl7.fhir.r5<=6.9.11
6.9.12

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade maven/ca.uhn.hapi.fhir:org.hl7.fhir.validation.cli to a version that resolves this vulnerability.

    Fixed in 6.9.12
  2. Upgrade

    Upgrade maven/ca.uhn.hapi.fhir:org.hl7.fhir.validation to a version that resolves this vulnerability.

    Fixed in 6.9.12
  3. Upgrade

    Upgrade maven/ca.uhn.hapi.fhir:org.hl7.fhir.r5 to a version that resolves this vulnerability.

    Fixed in 6.9.12

Event History

Sep 17, 2026
Advisory Published
via GitHub·08:32 PM
Data Sourced
via GitHub·08:32 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to this denial-of-service condition?

Any deployment using the listed FHIR validation or R5 components that accepts Smart Health Card content for validation is exposed if untrusted parties can submit that content. The issue can pin a JVM worker thread indefinitely.

2

What does an attacker need to send?

The attacker needs to submit a malformed SHC JWT whose header specifies "zip":"DEF" and whose raw DEFLATE payload is empty or truncated. No privileges or user interaction are required according to the supplied severity vector.

3

Does the malicious input need to be a valid Smart Health Card?

No. The trigger is a malformed SHC JWT with a DEF-compressed payload that is empty or truncated; processing reaches decompression based on the JWT header.

4

How can I determine whether my validation path is affected?

Review whether your application invokes SHC parsing or validation on attacker-controlled content and uses the listed artifacts. The affected code paths are SHCParser.inflate() and SHCParser.decompress(), which loop without handling an inflater that needs more input or makes zero progress.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203