Sep 18, 2026·7 min read·5 visits
Unbounded DEFLATE decompression in HAPI FHIR SHCParser allows remote attackers to cause JVM OutOfMemory crashes via malformed Smart Health Card payloads.
A critical denial of service vulnerability exists in the HAPI FHIR SHCParser within the org.hl7.fhir.core Java library. Unbounded decompression of raw DEFLATE data during Smart Health Card parsing allows unauthenticated remote attackers to trigger JVM heap exhaustion and crash the application.
The HAPI FHIR library, specifically within the org.hl7.fhir.core artifact, exposes a security flaw in its parsing mechanism for Smart Health Cards (SHC). The core of this issue resides within the SHCParser class, which handles JSON Web Tokens (JWT) structured as health credentials. Smart Health Cards are designed to store cryptographic proof of clinical data, such as vaccination records and laboratory test results, often utilizing compression to minimize the payload footprint for QR code generation.
The vulnerable parser processes these payloads without implementing restrictions on the maximum allowable size of decompressed data. This operational gap exposes applications leveraging this library to remote, unauthenticated Denial of Service (DoS) attacks. The attack vector belongs to the class of data amplification vulnerabilities, specifically categorized under CWE-409 (Improper Handling of Highly Compressed Data) and CWE-400 (Uncontrolled Resource Consumption).
A remote, unauthenticated attacker can exploit this weakness by transmitting a highly compressed, malformed JWT to any endpoint that validates or parses Smart Health Cards. The target application, upon receiving the payload, initiates decompression in memory, leading to rapid resource exhaustion. Because this process occurs automatically during JWT decoding, no prior authentication is required to trigger the vulnerability.
The vulnerability stems from the implementation of the inflate method within org.hl7.fhir.r5.elementmodel.SHCParser. When the parser processes an incoming JWT, it inspects the header for the "zip" parameter. If the parameter is set to "DEF", indicating DEFLATE compression, the parser forwards the raw payload bytes to the internal inflate utility function. This utility leverages the native java.util.zip.Inflater class to process the compressed byte stream.
The fundamental design flaw is the absence of any safety bounds within the decompression loop. The inflate method instantiates a ByteArrayOutputStream initialized with the size of the compressed data. It then iteratively calls inflater.inflate(buffer) inside a while (!inflater.finished()) loop. Each successfully decompressed chunk of bytes is appended directly to the output stream.
The loop continues to allocate memory and write bytes until the decompression engine reports completion. An attacker can construct a payload where a few kilobytes of compressed data inflate into hundreds of megabytes or gigabytes of plain text. Because the code lacks a validation check on the cumulative size of the written bytes, the JVM heap space is quickly consumed, leading to memory exhaustion.
To understand the mechanical vulnerability, we must examine the difference between the vulnerable code path and the patched implementation. Below is the vulnerable inflate method implementation as it existed in versions prior to 6.9.12:
// Vulnerable Implementation
public static ByteArrayOutputStream inflate(byte[] compressed) throws IOException, DataFormatException {
final Inflater inflater = new Inflater(true);
inflater.setInput(compressed);
try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(compressed.length)) {
byte[] buffer = new byte[BUFFER_SIZE];
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
if (count > 0) {
// Appending without checking the accumulated size
outputStream.write(buffer, 0, count);
} else {
if (inflater.needsInput() || inflater.needsDictionary()) {
break;
}
}
}
inflater.end();
return outputStream;
}
}The fix introduced in commit fbb94216e0ad21ded75be77e5e20242ba194e83f mitigates this issue by tracking the quantity of processed bytes and establishing an upper threshold based on MAX_ALLOWED_SHC_LENGTH.
// Patched Implementation
public static ByteArrayOutputStream inflate(byte[] compressed) throws IOException, DataFormatException {
final Inflater inflater = new Inflater(true);
inflater.setInput(compressed);
int writtenBytes = 0; // Track cumulative decompressed size
try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(compressed.length)) {
byte[] buffer = new byte[BUFFER_SIZE];
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
if (count > 0) {
outputStream.write(buffer, 0, count);
writtenBytes += count; // Increment cumulative count
// Enforce upper limit to block decompression bombs
if (writtenBytes > MAX_ALLOWED_SHC_LENGTH * 2) {
throw new DataFormatException("Maximum size of SHC JWT exceeded.");
}
} else {
if (inflater.needsInput() || inflater.needsDictionary()) {
break;
}
}
}
inflater.end();
return outputStream;
}
}This patch restricts memory usage during the decompression phase. By comparing writtenBytes to MAX_ALLOWED_SHC_LENGTH * 2 inside the tight loop, the execution context terminates immediately upon encountering a decompression ratio indicative of an attack. This defensive technique isolates the JVM heap from excessive allocations.
Exploitation of CVE-2026-81875 relies on constructing a highly compressed payload, commonly referred to as a "zip bomb," and wrapping it inside a JSON Web Token. The DEFLATE algorithm utilizes a combination of LZ77 and Huffman coding, which achieves extreme compression ratios when processing highly redundant datasets. An attacker can compress a stream consisting of 400 megabytes of repeating characters (e.g., ASCII character a) into a raw DEFLATE stream of less than 100 kilobytes.
The attacker then structures a JWT with two primary parts. The header must specify "zip": "DEF" to instruct the parser to invoke the inflate method. The payload section contains the base64url-encoded representation of the raw compressed byte stream. Once prepared, this token is sent via an HTTP POST or GET request to the target FHIR application's endpoint.
The application receiving the payload identifies the "zip" header and immediately transfers the compressed payload to the SHCParser.inflate method. The decompression loop begins executing on the CPU, inflating the byte stream into the JVM's heap memory. As memory allocation requests scale rapidly, garbage collection cycles are triggered repeatedly, consuming substantial CPU resources before the application ultimately halts due to a fatal java.lang.OutOfMemoryError.
The impact of successful exploitation is limited to availability but remains high due to the nature of Java memory exhaustion. When a JVM encounters an OutOfMemoryError on a thread, the stability of the entire container or process is compromised. Often, the application server becomes unresponsive, fails health checks, and crashes, requiring a manual restart or orchestrator intervention to restore service.
In cloud-native or containerized environments (e.g., Kubernetes), a crash of this nature triggers container restarts. If an attacker continuously sends malicious requests, they can induce a cyclic crash-loop, effectively rendering the clinical data service completely unavailable. This blocks critical operations, such as vaccine verification or medical record transfers, which rely on the processing of Smart Health Cards.
Because this vulnerability does not allow remote code execution or data extraction, the integrity and confidentiality of the system are unaffected. However, the CVSS score of 7.5 reflects the severity of the complete availability loss. Since exploitation requires no special privileges or user interaction and can be performed remotely, the vulnerability poses a significant operational risk to health IT infrastructures.
The recommended and most secure remediation path is upgrading the underlying HAPI FHIR core dependencies to version 6.9.12 or later. This ensures that the size-limit check is compiled into the SHCParser class and active on all endpoints processing Smart Health Cards. Developers should verify that all nested dependencies pulling in older versions of org.hl7.fhir.core are properly aligned.
For organizations unable to immediately deploy code changes, network-level mitigations can reduce exposure. Web Application Firewalls (WAF) or API Gateways can be configured to inspect incoming HTTP payloads for JWT tokens containing the "zip": "DEF" header. If found, these payloads can be rejected prior to reaching the application layer. Additionally, setting strict request body size limits at the gateway layer prevents attackers from transmitting very large tokens, though it does not prevent highly optimized zip bombs of smaller size.
Furthermore, the JVM runtime should be configured to handle OutOfMemory errors gracefully. Enabling flags such as -XX:+CrashOnOutOfMemoryError or -XX:+ExitOnOutOfMemoryError ensures that the JVM exits cleanly when heap space is exhausted, allowing container orchestrators to immediately spin up healthy instances and minimize overall downtime during an active attack.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
org.hl7.fhir.core HAPI FHIR | < 6.9.12 | 6.9.12 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-409 (Improper Handling of Highly Compressed Data) |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 7.5 (High) |
| EPSS Score | 0.0063 (Percentile: 48.59%) |
| Impact | Denial of Service (DoS) via JVM Heap Exhaustion |
| Exploit Status | Proof of Concept (PoC) Available |
| KEV Status | Not Listed |
Improper Handling of Highly Compressed Data (Data Amplification / Decompression Bomb)
A critical double-evaluation vulnerability exists in the rewrite module of the Caddy web server. Under specific configurations where a rewrite directive ends with a literal question mark and processes client-controlled headers, the system performs a secondary expansion pass. This allows attackers to evaluate arbitrary internal placeholder variables, leading to unauthorized disclosure of sensitive environment variables and system files.
CVE-2026-77615 is a high-severity Stored Cross-Site Scripting (XSS) vulnerability in the Paella Player component, which is integrated as the default front-end media viewer in Opencast. Unsafe client-side rendering of subtitle tracks allows authenticated, low-privileged users to inject arbitrary JavaScript payloads via crafted WebVTT or DFXP files. The script executes within the context of any viewer session under the host origin, enabling session hijacking and unauthorized API interaction.
A comprehensive technical analysis of six Cross-Site Scripting (XSS) vulnerability classes in the djust framework versions 1.0.0 through 1.1.0, involving escaping failures across the Python-Rust template boundary and stateful WebSocket cache lifecycles.
An escaping defect in the djust templating engine allows Cross-Site Scripting (XSS) when a template binding construct shadows a variable that was previously marked safe. The Rust-based context safety tracking incorrectly preserves name-based safety grants even after the variable name has been bound to a new, untrusted value.
CVE-2026-81876 is a high-severity Denial of Service vulnerability in HAPI FHIR, a complete Java implementation of the HL7 FHIR standard. The vulnerability stems from improper usage of Java's java.util.zip.Inflater class within the Smart Health Card (SHC) parser.
CVE-2026-82399 is a resource management vulnerability in CoreDNS affecting custom DNS transport pathways. Prior to version 1.14.7, transports including DNS-over-HTTPS (DoH), DNS-over-QUIC (DoQ), and DNS-over-gRPC executed the resource-intensive unpack method of the underlying Go DNS library on raw, untrusted incoming payloads before validating the fixed 12-byte DNS header. An unauthenticated remote attacker can exploit this behavior by using nested DNS name compression pointers to trigger substantial heap allocations, leading to memory exhaustion and server termination.