Sep 18, 2026·6 min read·2 visits
An unauthenticated remote attacker can trigger an infinite loop in the JVM by submitting a malformed JSON Web Token representing a Smart Health Card. This loop pins the worker thread at 100% CPU, leading to potential complete application Denial of Service.
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.
The HAPI FHIR framework, a widely utilized Java-based implementation of the HL7 Fast Healthcare Interoperability Resources standard, is vulnerable to an unauthenticated Denial of Service (DoS) flaw. This vulnerability is tracked as CVE-2026-81876.
At the core of this vulnerability is the Smart Health Card (SHC) parser, implemented in SHCParser.java within the org.hl7.fhir.core ecosystem. Smart Health Cards are typically transferred as JSON Web Signatures (JWS) and can utilize compressed formats to reduce payload size. When processing these tokens, the framework attempts to decompress the nested payloads using Java's standard decompression APIs.
While the issue originates in the SHC-specific parsing module, the overall attack surface is significantly wider. Applications that do not explicitly process Smart Health Cards can still expose this vulnerability through automatic format detection features. Specifically, the framework utilizes ResourceChecker.java to dynamically determine the schema of arbitrary incoming data streams, routing them automatically through the vulnerable decompression logic if certain structural patterns are matched.
The root cause of CVE-2026-81876 lies in an unsafe processing loop within SHCParser.java during DEFLATE decompression. The parser leverages Java's native java.util.zip.Inflater class to process payloads indicating DEFLATE compression via the zip: DEF JWS header parameter.
The vulnerable implementation used a loop structured around the termination condition !inflater.finished(). However, the Java Development Kit (JDK) API contract for java.util.zip.Inflater specifies that finished() returns true only when the end of the compressed data stream is successfully reached. If the input stream is truncated, structurally incomplete, or empty, the decompression state machine cannot reach the official stream termination point.
Under these malformed conditions, invoking inflater.inflate(buffer) returns 0, indicating that zero bytes were processed. Because the stream did not terminate cleanly, finished() remains false, while needsInput() transitions to true to request more data. Since the code did not inspect the return value of inflate() or check needsInput(), the loop continues to execute indefinitely. This results in a CPU-bound infinite loop that pins the executing JVM thread at 100% capacity.
The vulnerable decompression logic in HAPI FHIR was present in multiple locations within SHCParser.java. Specifically, both the public inflate method and the private decompress helper method contained identical vulnerable looping patterns.
The following code snippet illustrates the original implementation of the public inflate method:
// VULNERABLE CODE - SHCParser.java
public static byte[] inflate(byte[] data) throws IOException, DataFormatException {
final Inflater inflater = new Inflater(true);
inflater.setInput(data);
try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) {
byte[] buffer = new byte[BUFFER_SIZE];
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
// Vulnerability: No check if count is 0 or if inflater has stalled
outputStream.write(buffer, 0, count);
}
return outputStream.toByteArray();
}
}The fix, introduced in commits d804558bd77372b1629e55a5b901cad3f5134cdc and edd5d8c139e669e39270785f08be7b63aefef24c, introduces explicit validation checks on the return value of the inflate() call. When the returned byte count is zero, the code evaluates the state of the inflater to decide whether to abort the loop:
// PATCHED CODE - SHCParser.java
public static byte[] inflate(byte[] data) throws IOException, DataFormatException {
final Inflater inflater = new Inflater(true);
inflater.setInput(data);
try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) {
byte[] buffer = new byte[BUFFER_SIZE];
while (!inflater.finished()) {
final int count = inflater.inflate(buffer);
if (count > 0) {
outputStream.write(buffer, 0, count);
} else {
// Handle the 0 byte return condition
if (inflater.needsInput()) {
// Break out if no more input chunks are available
break;
}
if (inflater.needsDictionary()) {
// Break out if a preset dictionary is missing
break;
}
}
}
return outputStream.toByteArray();
}
}This defensive pattern is robust against malformed or truncated payloads, preventing the infinite loop by exiting when the utility requires input that is not provided. However, the patch does not limit the maximum decompressed size. This omission means the parser remains potentially susceptible to decompression bombs (zip bombs) where a small, valid payload decompresses into an excessively large byte array, which could deplete JVM memory.
Exploitation of CVE-2026-81876 is highly practical and requires only network access to any open endpoint that processes FHIR data. Because of the behavior of automatic format detection, the attacker does not need to target an explicit Smart Health Card upload mechanism.
The conceptual attack path involves the following steps:
First, the attacker constructs a compact JWS token with a header containing the "zip": "DEF" attribute. The payload component of the token is intentionally left empty or truncated, so that it fails to provide the termination sequence required by the DEFLATE algorithm.
Second, the attacker transmits this token within an HTTP request to any endpoint utilizing ResourceChecker or direct FHIR parsers. Upon parsing, the application routes the token to SHCParser.inflate() or SHCParser.decompress() based on the header instruction.
Third, the decompression engine encounters the truncated input, fails to make progress, and enters the infinite loop. By executing a series of concurrent requests matching this structure, an attacker can consume all available threads in the JVM thread pool, inducing complete application Denial of Service.
The primary impact of CVE-2026-81876 is a complete Denial of Service of the hosting JVM. Because the infinite loop is entirely CPU-bound, a single thread spinning at 100% utilization consumes resources that are otherwise shared with legitimate application functions.
In standard application server configurations, thread pools manage incoming HTTP requests. If an attacker delivers multiple concurrent malformed JWS payloads, they can quickly exhaust the pool of active worker threads. Once the thread pool is fully occupied by infinite decompression loops, the application can no longer accept or process legitimate traffic, resulting in downtime.
From a scoring perspective, this vulnerability represents a severe threat despite not allowing remote code execution or data exposure. The lack of authentication requirements, coupled with low complexity and high exploit reliability, justifies the CVSS v3.1 score of 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).
The most effective remediation is upgrading the core HAPI FHIR library. All deployments using the org.hl7.fhir.core family of libraries must upgrade to version 6.9.12 or later to eliminate the vulnerable decompression logic.
Where immediate updates are not feasible, network-level mitigations should be applied. Web Application Firewalls (WAF) can be configured to inspect incoming payloads for JSON Web Signature patterns containing the deflate parameter. Specifically, rules should block or alert on strings matching the "zip":\s*"DEF" pattern within HTTP request bodies.
Additionally, operations teams should monitor JVM performance metrics. A sudden, unexplained rise in CPU usage to 100% across multiple threads, combined with an increasing rate of HTTP request timeouts, serves as a strong indicator of an active exploitation attempt.
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 hapifhir | < 6.9.12 | 6.9.12 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-835 / CWE-400 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.0063 |
| Impact | Denial of Service (DoS) |
| Exploit Status | Theoretical / Unproven |
| KEV Status | Not Listed |
Loop with Unreachable Exit Condition ('Infinite Loop')
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.
An infinite loop vulnerability in ReactPHP's react/http chunked transfer encoding decoder (v0.6.0 up to 1.11.1) allows unauthenticated remote attackers to trigger a denial of service (DoS) by sending crafted chunked requests or responses, completely freezing the single-threaded event loop and pegging CPU usage to 100%.
Plate core HTML deserialization APIs parse supplied HTML strings in the active document. When an application passes untrusted or cross-user HTML to these APIs, certain HTML attributes can trigger browser behavior before the HTML is converted into editor nodes.
A polynomial-time Regular Expression Denial of Service (ReDoS) vulnerability in Soup Sieve versions prior to 2.9 allows remote unauthenticated attackers to cause CPU exhaustion and thread-pool denial of service. The vulnerability resides in the trailing whitespace and comment preprocessing step of the CSS parser. An attacker can trigger quadratic backtracking by submitting a crafted CSS selector string containing a long run of internal spaces or comments terminated by a non-matching token. This blocks the Python Global Interpreter Lock (GIL) and halts worker threads.
A regular expression denial of service (ReDoS) vulnerability in Soup Sieve prior to version 2.9 allows remote attackers to cause CPU exhaustion and service disruption. The issue lies within the definition of the IDENTIFIER and VALUE selector sub-patterns in the CSS parser component, which uses overlapping adjacent quantified groups. When parsing long, crafted, or unclosed CSS selectors, backtracking-based regular expression engines experience quadratic performance degradation. User-controlled selectors can reach this path through soupsieve.compile(), soupsieve.select(), or BeautifulSoup.select(), while applications using only hard-coded selectors are unaffected.
A protocol-level validation bypass in CoreDNS versions prior to 1.14.7 allows unauthenticated remote attackers to proxy unauthorized DNS UPDATE messages (Opcode 5) using modern alternative transport layers such as DoH, DoH3, DoQ, and gRPC. If upstream authoritative servers trust the CoreDNS server's source IP and do not enforce TSIG authentication, attackers can inject, alter, or delete DNS zone records, leading to potential zone takeover or traffic redirection.