On 22 October 2026 CISA published advisory VA-26-294-01 with four CVEs in HAPI FHIR, the open source Java FHIR server. The worst, CVE-2026-113874 (CVSS 8.1), lets a caller authorized for one tenant read or create data in another tenant's partition. Three of the four have no fix. Mitigate now with a partition entitlement interceptor and gateway rules.
This is a vulnerability disclosure, not a breach. No exploitation is reported. None of the four CVEs is in the CISA Known Exploited Vulnerabilities (KEV) catalog as of the 23 October release, and CISA's decision notes record exploitation status as "none." The researcher has withheld his proof of concept code until released versions fix the remaining findings.
What makes this disclosure unusual is the fix status. For three of the four CVEs, CISA's advisory says "No fix available." The next major release, 9.0.0, is scheduled for 19 November 2026 and, according to the researcher, is a breaking upgrade with no 8.x backport. Until then the mitigations are in your hands, and they are configuration and interceptor changes a Java team can ship this week.
What happened
HAPI FHIR is the most widely used open source implementation of HL7 FHIR in Java. It ships as a set of Maven libraries under the ca.uhn.hapi.fhir group, as a reference JPA server, and as a Docker image. It sits underneath many commercial and public sector FHIR products. CISA lists the vendor as SmileCDR, the company that maintains the project.
An independent researcher, Abhinav Agarwal, reported four findings against HAPI FHIR 8.10.0 (commit 96ac50f89455). The case was coordinated through CERT/CC as VU#394579. On 22 October CISA, acting as CVE Numbering Authority under its cisa-cg short name, published a CSAF advisory and the four CVE records. A few hours later the researcher posted a technical summary to the oss-security mailing list and published a longer write-up on his own site.
The four findings, in CISA's titles:
| CVE | CISA title | CWE | CVSS 3.1 | Fix status per CISA |
|---|---|---|---|---|
| CVE-2026-113874 | trusted tenant partition override | CWE-863 Incorrect Authorization | 8.1 High | No fix available |
| CVE-2026-113873 | improper data decompression | CWE-409 Improper Handling of Highly Compressed Data | 7.5 High | No fix available |
| CVE-2026-113876 | unauthorized read | CWE-863 Incorrect Authorization | 4.3 Medium | "Fixed around September 2026" |
| CVE-2026-113875 | unauthorized read via subscription | CWE-862 Missing Authorization | 3.1 Low | No fix available |
CISA's risk summary is short. In the worst case, it says, "a user could read or write content in a tenant partition that they should not have access to, or an unauthenticated user could trigger a denial-of-service." Its recommended practice is to update to the most recent available version, but as the rest of this post shows, the most recent release does not contain any of the fixes.
Timeline
All times are UTC unless stated. Each row names the source we read.
| Date and time | Event | Source |
|---|---|---|
| 21 May 2026, 19:12 | HAPI FHIR v8.10.0 released (the version the researcher tested) | GitHub releases |
| 11 to 12 Jul 2026 | Findings confirmed against commit 96ac50f89455, each with a passing test | Researcher write-up |
| 12 Jul 2026, 11:24 | Coordination case VU#394579 opened | oss-security post |
| 22 Jul 2026, 21:11 | v8.10.1 released | GitHub releases |
| 13 Aug 2026, 21:04 | Upstream issue #8253 opened: AuthorizationInterceptor does not read authorize write response bodies (PATCH, conditional create). The researcher describes this as an independent upstream report of the conditional create path | GitHub issue #8253 |
| 19 Aug 2026, 19:20 | PR #8254 "Read authorize patch and conditional create responses" merged to master as commit 063b073e8c1 | GitHub PR #8254 |
| 1 Sep 2026, 16:31 | v8.12.0 released | GitHub releases |
| 15 Sep 2026, 06:29 | v8.12.1 released, the newest version on Maven Central | GitHub releases, Maven Central |
| 22 Sep 2026, 19:22 | PR #8404 merged to master: STORAGE_PARTITION_SELECTED now fires for partition selecting requests without a resource type | GitHub PR #8404 |
| 25 Sep 2026, 21:05 | v8.8.2 released (maintenance line) | GitHub releases |
| 6 Oct 2026, 16:13 to 17:12 | CISA records its SSVC decisions for the four CVEs | CISA CSAF VA-26-294-01 |
| 20 Oct 2026, 20:11 to 20:12 | CVE IDs reserved | CVE records |
| 22 Oct 2026, 17:14:18 | CISA publishes CSAF advisory VA-26-294-01, version 1.0.0, TLP WHITE | CISA CSAF |
| 22 Oct 2026, 17:57:52 to 18:00:15 | CVE-2026-113873, 113874, 113875 and 113876 records published | CVE records |
| 22 Oct 2026, 15:42 PDT (22:42 UTC) | Researcher posts the disclosure to oss-security | Openwall archive |
| 23 Oct 2026, 19:30 | KEV catalog version 2026.10.23 released; none of the four CVEs listed | CISA KEV feed |
| 19 Nov 2026 (scheduled) | HAPI FHIR 9.0.0, which the researcher says carries the conditional create change but is a breaking upgrade | Researcher write-up |
Who is affected
The CVE records list every version of HAPI FHIR as affected for three of the CVEs. In CVE terms, the affected range runs from version 0 with no upper bound, and the default status is "unknown." For CVE-2026-113876 the affected range is "less than September 2026," which is a date, not a version number. We return to that oddity below.
The researcher's own scope is more precise. He tested 8.10.0. Reading the source on 22 October, he found all four code paths present in v8.8.2, v8.10.1 and v8.12.1. On master, three paths are unchanged and the conditional create response body is suppressed. The partition extension handler behind CVE-2026-113874 first shipped in v8.2.0.
Being on an affected version is necessary but not sufficient. Each bug needs a particular configuration. This table, built from the researcher's prerequisites list and module names, is the one to work through with your platform team:
| CVE | Module | Exposed only if | Default state |
|---|---|---|---|
| CVE-2026-113874 | hapi-fhir-storage (JPA) | Partitioning is on, tenant routing uses RequestHeaderPartitionInterceptor fed by a trusted header, callers can POST transaction or batch Bundles, and no STORAGE_PARTITION_SELECTED entitlement hook is registered | HAPI ships no entitlement hook |
| CVE-2026-113873 | hapi-fhir-server | Inbound decompression is on and some reachable operation reads a request body | Decompression is on by default |
| CVE-2026-113876 | hapi-fhir-server, hapi-fhir-storage | AuthorizationInterceptor grants CREATE without READ on a resource type | Default response is the full representation |
| CVE-2026-113875 | hapi-fhir-jpaserver-subscription | REST hook subscriptions are enabled and non administrators can create Subscription resources | REST hook subscriptions are off by default |
Who that means in practice
Single tenant servers have no tenant boundary to cross, so CVE-2026-113874 does not apply, though the other three may. The override matters most where one HAPI JPA database holds several organisations' data and a gateway picks the partition: payer to payer exchange, health information exchanges, multi-tenant SaaS EHR and shared internal platforms. The gzip bug matters for anything reachable from an untrusted network.
Downstream products
The researcher counted, as of 22 October, 2,254 GitHub repositories declaring hapi-fhir-base and about 25.3 million Docker pulls of hapiproject/hapi since December 2019. He notes these count different things and include forks, so treat them as scale, not a census.
He also reports that Smile CDR's changelog maps Smile CDR 2026.05.R01 to HAPI FHIR 8.10.0, 2026.05.R02 to 8.10.1, 2026.08.R02 to 8.12.1 and 2026.02.R03 to 8.8.2. He did not test Smile CDR, which has its own modules, so the mapping alone does not show any finding is reachable there. We could not load the changelog to confirm it. Do not assume a product built on HAPI is affected, or that it is safe. Ask your supplier for a written statement on each CVE and the exact build that addresses it.
How the four issues work
This section explains each bug in plain terms so you can judge exposure. It names the vulnerable methods, which help when reading your own code and logs, and leaves out request bodies and test code.
CVE-2026-113874: the partition header gets overwritten
In a typical multi-tenant setup, a gateway authenticates the caller, removes any partition header the caller sent, and writes the caller's tenant into X-Request-Partition-IDs. HAPI's RequestHeaderPartitionInterceptor reads that trusted header and picks the partition.
FHIR also lets a client send many operations in one transaction or batch Bundle, and HAPI processes each entry as a sub-request. Since v8.2.0, HAPI has honoured a per-entry request-partition-ids extension. When an entry carries it, BaseTransactionProcessor.setRequestPartitionHeaderIfEntryHasTheExtension() copies its value into the sub-request's partition header with no authorization check, according to the researcher. The value the gateway set is replaced by one that came from the request body.
The partition then reaches the STORAGE_PARTITION_SELECTED pointcut, which HAPI's documentation describes as the place where an interceptor can "make decisions about whether the request should be allowed to proceed." HAPI does not ship such an interceptor. CISA puts it plainly: HAPI "does not enforce storage partition entitlement by default."
In the researcher's tests, one batch request read Patient records from three partitions, and a transaction created a Patient in a foreign partition. He did not test changing or deleting existing foreign records. A control test with an entitlement hook blocked the override. The gateway did its job; the server trusted something the gateway never saw.
CVE-2026-113873: decompression before authorization
HAPI's RestfulServer decompresses inbound request bodies by default; the javadoc for setUncompressIncomingContents says the default is true. With Content-Encoding: gzip, the body is inflated into memory with no limit on size or ratio.
This happens while HAPI builds method parameters, before AuthorizationInterceptor runs, so no authorization is needed (PR:N). In the researcher's test, a 65,250 byte body expanded to 64 MiB, about 1,028 to 1, and in a JVM with a 64 MiB heap a body of about 255 KB triggered OutOfMemoryError. He called the routine directly and did not measure an outage of a running server. CISA's SSVC notes mark this one as automatable.
CVE-2026-113876: conditional create shows a record you cannot read
FHIR conditional create, via the If-None-Exist header, means "create this, unless a match exists." On a match HAPI creates nothing and, by default, returns the existing record in full. AuthorizationInterceptor treats CREATE as inbound, and its outgoing check returns early for inbound operations. So a caller with CREATE but no READ can receive a full stored record, provided it already knows a search value matching exactly one. The researcher did not demonstrate enumeration.
Upstream PR #8254 now suppresses the body when a CREATE creates nothing. The researcher notes it does not add a read check: the matched id still returns in the Location header, and 200 versus 201 still reveals whether a match existed.
CVE-2026-113875: subscriptions deliver more than the creator can read
REST hook subscriptions, off by default, push matching resources to a URL the subscriber chooses. The researcher found that neither creation nor delivery applies the creator's read rules; delivery reloads the resource as SystemRequestDetails, a full privilege internal identity. In his test, an Observation from another patient's compartment, same partition, reached the subscriber's endpoint though the subscriber could not read it directly. This is a read scope bypass, not a cross-tenant leak.
Technical details
Every value below comes from the CISA CSAF document, the CVE records, the researcher's oss-security post and write-up, the HAPI FHIR GitHub repository or the HAPI FHIR documentation. There are no file hashes, IP addresses or domains to list: this is a vulnerability disclosure with no reported exploitation, and no source publishes indicators of compromise.
Advisory identifiers
| Item | Value | Source |
|---|---|---|
| CISA advisory | VA-26-294-01, CSAF 2.0, category csaf_vex, version 1.0.0, status final | CISA CSAF |
| Initial and current release | 2026-10-22T17:14:18Z | CISA CSAF |
| Generator | VINCE-NT 1.15.0+build.129 | CISA CSAF |
| Coordination case | CERT/CC VU#394579, opened 2026-07-12 11:24 UTC | oss-security post |
| CNA | cisa-cg | CVE records |
| Vendor as listed | SmileCDR, product HAPI FHIR | CISA CSAF, CVE records |
| Sectors and deployment | Information Technology; Worldwide; headquarters United States | CISA CSAF |
| Credit | Abhinav Agarwal | CVE records |
The researcher notes that VA-26-294-01 is CISA's machine readable CSAF record and that, as of his post, a traditional human readable CISA advisory had not been published.
Per-CVE detail
| CVE | Vector | Published (UTC) | Reserved (UTC) | SSVC decision string |
|---|---|---|---|---|
| CVE-2026-113874 | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N | 2026-10-22 17:58:56 | 2026-10-20 20:11:55 | SSVCv2/E:N/A:N/T:P/2026-10-06T16:14:15Z/ |
| CVE-2026-113873 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | 2026-10-22 17:57:52 | 2026-10-20 20:11:47 | SSVCv2/E:N/A:Y/T:P/2026-10-06T16:13:10Z/ |
| CVE-2026-113876 | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N | 2026-10-22 18:00:15 | 2026-10-20 20:12:13 | SSVCv2/E:N/A:N/T:P/2026-10-06T17:12:44Z/ |
| CVE-2026-113875 | CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N | 2026-10-22 18:00:01 | 2026-10-20 20:12:03 | SSVCv2/E:N/A:N/T:P/2026-10-06T16:15:54Z/ |
In CISA's SSVC notation, E:N means exploitation status none, A:Y or A:N means automatable yes or no, and T:P means partial technical impact.
Affected and fixed versions
| CVE | CVE record affected range | Researcher's source check, 22 Oct | Fixed in a release? |
|---|---|---|---|
| CVE-2026-113874 | version 0, less than * (all) | Present in v8.8.2, v8.10.1, v8.12.1 and master; handler unchanged; introduced in v8.2.0 (commit 85abdc23007) | No |
| CVE-2026-113873 | version 0, less than * (all) | Present; ServletRequestDetails.java byte identical across every ref inspected | No |
| CVE-2026-113875 | version 0, less than * (all) | Present; no commits to the relevant classes | No |
| CVE-2026-113876 | less than September 2026; September 2026 unaffected | Body suppression in 063b073e8c1 on master and the rel_9_0 branch only | No released tag as of 22 Oct; scheduled for 9.0.0 |
Released versions on Maven Central for ca.uhn.hapi.fhir:hapi-fhir-base, newest first, with GitHub release dates: 8.12.1 (15 Sep), 8.12.0 (1 Sep), 8.10.1 (22 Jul), 8.10.0 (21 May), 8.8.2 (25 Sep, maintenance line), 8.8.1, 8.8.0, 8.6.8. Per the researcher, none of these contains a fix for any of the four CVEs.
Vulnerable code locations
These method names come from the researcher's write-up and oss-security post. Line numbers there refer to commit 96ac50f89455.
| CVE | Class and method | Role |
|---|---|---|
| CVE-2026-113874 | BaseTransactionProcessor.setRequestPartitionHeaderIfEntryHasTheExtension() | Copies the entry extension value over the sub-request partition header |
| CVE-2026-113874 | ServletSubRequestDetails.setHeaders() | Replaces the sub-request headers (remove all, then put all) |
| CVE-2026-113874 | BaseRequestPartitionHelperSvc.validateAndNormalizePartition() | Broadcasts STORAGE_PARTITION_SELECTED, where an entitlement hook can block |
| CVE-2026-113873 | ServletRequestDetails.getByteStreamRequestContents() | Inflates gzip bodies with no cap |
| CVE-2026-113873 | RestfulServer field myUncompressIncomingContents | Defaults to true |
| CVE-2026-113876 | AuthorizationInterceptor.hookPreShow() and checkOutgoingResourceAndFailIfDeny() | Skips the outgoing check for inbound operations such as CREATE |
| CVE-2026-113876 | BaseHapiFhirResourceDao.doCreateForPostOrPut() | Returns the stored entity on a single match |
| CVE-2026-113875 | SubscriptionValidatingInterceptor.validateSubmittedSubscription() | Does not apply the creator's read policy at creation |
| CVE-2026-113875 | SubscriptionDeliveringRestHookListener.getResource() | Reloads the resource as SystemRequestDetails at delivery |
Key strings to search for
| String | Where it matters |
|---|---|
http://hapifhir.io/fhir/ns/StructureDefinition/request-partition-ids | The Bundle entry extension URL behind CVE-2026-113874. Search gateway logs, stored request bodies and your own client code for it |
X-Request-Partition-IDs | The trusted header your gateway sets for RequestHeaderPartitionInterceptor |
RequestHeaderPartitionInterceptor | Tells you a server uses header based tenant routing |
STORAGE_PARTITION_SELECTED | If no class in your code hooks this pointcut, you have no partition entitlement check |
setUncompressIncomingContents | If your code never calls this with false, inbound gzip decompression is on |
If-None-Exist | Conditional create header for CVE-2026-113876 |
rest-hook | Subscription channel type for CVE-2026-113875 |
A related upstream change to know about
Upstream PR #8404, merged to master on 22 September, says that before it, STORAGE_PARTITION_SELECTED "was only fired when the request carried a resource type." Partition selecting requests without one, such as system level _history, result paging, transactions and server level operations, skipped the hook. The PR description says this let a client scoped to one partition read another partition's data. The researcher says the change is unreleased, adds no entitlement policy, and leaves the extension handler unchanged.
That matters for your mitigation. In the researcher's tests, the entitlement hook blocked the override on typed entries inside a Bundle. But on released versions, a hook alone does not cover untyped, partition selecting requests. Pair it with gateway rules, described below.
What to do now
Work through these steps in order. The first two tell you whether you are exposed at all. Steps 3 to 6 are the four mitigations. Step 7 is how you verify.
1. Find every HAPI FHIR in your estate
HAPI often hides inside other things: a Spring Boot fat jar, a vendor appliance, an integration engine, a test harness that ended up in production.
For Maven projects:
mvn -q dependency:tree -Dincludes=ca.uhn.hapi.fhir
For Gradle projects:
./gradlew dependencies --configuration runtimeClasspath | grep 'ca.uhn.hapi.fhir'
For built artifacts, including Spring Boot jars that keep dependencies under BOOT-INF/lib:
unzip -l app.jar | grep -E 'hapi-fhir-(base|server|storage|jpaserver)'
find / -name 'hapi-fhir-*.jar' 2>/dev/null
For container images and SBOM files, scan with the Safeguard CLI, which writes JSON results under ./output:
safeguard scan --image registry.example.com/fhir-server:prod
safeguard scan --sbom fhir-server.cdx.json
safeguard scan --dir .
Record, for each hit, the HAPI version, which modules are present (hapi-fhir-jpaserver-base and hapi-fhir-storage matter for the partition bug, hapi-fhir-jpaserver-subscription for subscriptions), and who owns the service.
For products you buy rather than build, ask the supplier three questions in writing: which HAPI FHIR version and modules the product contains, whether each of the four CVEs is reachable in the product's configuration, and which exact build fixes or mitigates each one.
2. Check whether the risky configuration is on
Search your server code for the strings in the table above:
grep -rn --include=*.java -E 'RequestHeaderPartitionInterceptor|RequestTenantPartitionInterceptor|STORAGE_PARTITION_SELECTED|setUncompressIncomingContents|AuthorizationInterceptor|SubscriptionSettings|rest-hook' src/
Then answer, for each server:
- Does a gateway header decide the partition? If yes, CVE-2026-113874 is the priority.
- Can tenant callers POST transaction or batch Bundles to the base endpoint? If the gateway allows
POST /fhir, assume yes. - Does any class hook
STORAGE_PARTITION_SELECTED? If not, there is no entitlement check. - Does the code call
setUncompressIncomingContents(false)? If not, inbound gzip is on. - Do any rules grant CREATE on a type without READ?
- Are REST hook subscriptions enabled, and who can create one?
3. CVE-2026-113874: add a partition entitlement check and strip the extension
There are two controls. Use both.
Control A, in HAPI: register a STORAGE_PARTITION_SELECTED interceptor. The researcher tested this control and it blocked the override. The hook receives the selected RequestPartitionId and the RequestDetails. Its job is to compare the final partition with the partitions the authenticated caller is entitled to, and to refuse anything else.
The critical design point: do not derive the caller's entitlement from X-Request-Partition-IDs inside this hook. That header is exactly the value the transaction processor overwrites on the sub-request. Derive entitlement from the authenticated identity instead, for example a validated token claim, or a value you stored on the parent request in an earlier hook before Bundle processing began.
A minimal sketch, to adapt and test against the javadoc for your HAPI version:
@Interceptor
public class PartitionEntitlementInterceptor {
private final TenantEntitlements entitlements; // your own lookup, keyed by authenticated principal
public PartitionEntitlementInterceptor(TenantEntitlements entitlements) {
this.entitlements = entitlements;
}
@Hook(Pointcut.STORAGE_PARTITION_SELECTED)
public void checkPartition(RequestPartitionId selected, RequestDetails request) {
if (request == null) {
return; // internal system work; review whether this is acceptable in your deployment
}
if (selected.isAllPartitions()) {
throw new ForbiddenOperationException("All-partition access is not permitted");
}
Set<Integer> allowed = entitlements.allowedPartitionIdsFor(request); // from the token, not the header
for (Integer id : selected.getPartitionIds()) {
if (!allowed.contains(id)) {
throw new ForbiddenOperationException("Partition not permitted for this caller");
}
}
}
}
Points to get right:
- Decide how to treat the default partition, stored as a null
PARTITION_ID, and partition names if you use them. - Register the interceptor on the same registry as your partition interceptors.
- Test each case: own partition allowed, foreign partition refused, default partition per your rule, a batch with mixed entries refused.
- Remember PR #8404: on released versions the hook does not fire for partition selecting requests without a resource type. Control B covers that gap.
Control B, at the gateway: refuse the extension and limit untyped operations. Your gateway already strips a caller supplied X-Request-Partition-IDs header. Treat the per-entry extension the same way. The simplest rule is to reject, with HTTP 400, any request body that contains the extension URL string. Rejecting is clearer than silently removing it, and you can log the event. If no legitimate client of yours uses per-entry partition routing, nothing should break.
For gateways that can inspect JSON, the check is whether any Bundle.entry.request.extension.url equals the extension URL. A blunt string match on the raw body also works and catches XML Bundles:
# Example logic for a gateway plugin or a quick log review
grep -l 'hapifhir.io/fhir/ns/StructureDefinition/request-partition-ids' /var/log/fhir-gateway/bodies/*
Then review which untyped endpoints tenant callers can reach: system level _history, paging links, server level operations and the base endpoint for transactions. If tenants do not need them, block them at the gateway for tenant scoped credentials.
4. CVE-2026-113873: switch off inbound decompression or cap it
If your clients do not send compressed request bodies, turn decompression off in HAPI:
restfulServer.setUncompressIncomingContents(false);
The javadoc says this setting should normally stay true unless something else handles decompression, so confirm first that no client relies on it. Check your access logs for Content-Encoding on inbound requests before you change it.
You can also refuse compressed bodies at the reverse proxy. For example, in nginx:
if ($http_content_encoding ~* "gzip|deflate") {
return 415;
}
If some clients do need compression, enforce a limit on the decompressed size before the body reaches HAPI, in a servlet filter or a proxy that decompresses and counts. The researcher is explicit that a cap on the compressed size alone, such as nginx client_max_body_size, is not enough, because a small compressed body can expand by three orders of magnitude.
As defence in depth, alert on JVM heap pressure and OutOfMemoryError in the FHIR server, and make sure the orchestrator restarts a crashed pod.
5. CVE-2026-113876: audit CREATE without READ
List every authorization rule that allows CREATE on a resource type, and check whether the same caller can READ that type. In a typical AuthorizationInterceptor subclass, that means reviewing buildRuleList for allow().create() rules that have no matching allow().read() rule.
grep -rn --include=*.java -E 'allow\(\)\.create\(\)|allow\(\)\.read\(\)|allow\(\)\.write\(\)' src/
Where CREATE without READ is a real business need, for example an intake system that files new records but must not browse them, suppress the response body for conditional creates that matched an existing record on the server side. The researcher notes that the client's Prefer: return=minimal header does not help, because the caller chooses it. He also notes that a ConsentInterceptor can cover this path, but only if its policy is written to do so.
CISA says this one was "Fixed around September 2026," without naming a release. The researcher found the fix only on master and the 9.0 branch. Until you can run a release that contains commit 063b073e8c1, treat CVE-2026-113876 as unfixed in your environment.
6. CVE-2026-113875: lock down subscription creation
Restrict creating and updating Subscription resources to administrators. Then audit what already exists, with an administrator token:
curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
"https://fhir.example.com/fhir/Subscription?status=active&type=rest-hook&_elements=criteria,channel,status" \
| jq '.entry[]?.resource | {id, criteria, endpoint: .channel.endpoint}'
Look for broad criteria (for example a whole resource type with no patient or organisation filter) and endpoints outside domains you control. The researcher notes that egress blocking stops delivery to a blocked destination but does not add a read check, so it is a partial control. If you do not use REST hook subscriptions at all, keep them disabled.
7. Verify
- Keep the entitlement interceptor tests in CI.
- On a test instance with synthetic data, confirm the gateway rejects the extension URL and the interceptor refuses a foreign partition when the gateway is bypassed.
- Confirm compressed requests are refused or capped.
- Record the HAPI version and these controls in the service's security notes, so the 9.0.0 upgrade does not silently remove them.
How to look for signs of misuse
There is no reported exploitation, so there are no published indicators to hunt for. You can still check your own data for the patterns these bugs would leave.
- Extension URL in logs. If request bodies are logged, search for the
request-partition-idsURL from clients that should never use it. - Batch volume per tenant. A sudden rise in read heavy transaction or batch POSTs from one tenant's credentials.
- Records in unexpected partitions. HAPI stores a
PARTITION_IDper resource; compare it with the tenant credential your audit trail says created the record. - Conditional creates that matched. Status 200 responses to POSTs carrying
If-None-Existfrom callers lacking READ on that type. - Subscriptions and memory. New Subscriptions with broad criteria or unfamiliar endpoints, and
OutOfMemoryErroror pod restarts that line up with compressed requests.
If you find something, treat it as a potential health data incident, including your reporting obligations.
What changed since first reports
The disclosure is two days old as of this review. Since the CISA publication on 22 October:
- The researcher's oss-security post and write-up added module level prerequisites, method names, the v8.2.0 origin of the extension handler and the 9.0.0 schedule, none of which appear in the CSAF record.
- KEV catalog version 2026.10.23, released on 23 October, does not list any of the four CVEs.
- We found no vendor statement or vendor advisory from SmileCDR or the HAPI FHIR project about the four CVEs. Check the HAPI FHIR GitHub repository and release notes for updates.
Open questions
- What does "Fixed around September 2026" mean for CVE-2026-113876? CISA's record names a date, not a version. The researcher found the response body change only on master and the 9.0 branch, and in no release tag. Neither source explains the gap. The researcher advises operators to get an exact fixed build statement from their supplier.
- When will the other three be fixed? No fix date exists for CVE-2026-113873, CVE-2026-113874 or CVE-2026-113875. The PR #8404 change is related but does not fix the extension handler.
- Will 8.x get a backport? The researcher says 9.0.0 is a breaking Spring Boot 4, Jackson 3 and Hibernate 7 upgrade with no 8.x backport. We did not find a project statement confirming or contradicting that.
- Which downstream products are reachable? Unknown. Commercial distributions and products that embed HAPI may or may not expose these paths, depending on their modules and configuration.
What would have helped
None of these bugs is exotic. Each is a trust decision made in one layer and undone, or never made, in another. These practices help with this disclosure and the next one like it.
Practices any team can use
- Enforce tenancy where the partition is finally chosen, not only at the edge. A gateway header is a routing decision; an entitlement check at storage is a security decision. It should not read anything the caller can influence.
- Treat every body field that changes routing as untrusted. Extensions that select a tenant or partition deserve the same stripping as the partition header.
- Bound everything that inflates. Decompression, Bundle size and entry counts need limits before authorization work starts.
- Write negative tests for authorization. For each role, test what it must not do: read a foreign partition, read through a write response, receive subscription data it cannot read.
- Keep a living inventory of embedded libraries. When the answer is "all versions, no fix," the first question is where it runs. An SBOM per service and image answers that in minutes. See using SBOMs to find affected products fast.
- Ask suppliers about components, not just products. Contracts that require component disclosure and fix statements make this week's questions faster to answer.
- Plan the major upgrade now. If 9.0.0 is the first release with any fix, teams already testing against Spring Boot 4, Jackson 3 and Hibernate 7 will move fastest.
We have written before about why FHIR on its own does not provide the controls a production deployment needs: see FHIR is not a security protocol and FHIR security is not built in. Earlier HAPI FHIR issues we covered include the Saxon XXE in CVE-2026-55471, the credential prefix match in CVE-2026-34359 and the validator loading issue in CVE-2026-34361.
Zero-Day Discovery and Gold
Safeguard's Zero-Day Discovery looks for previously unknown flaws before a CVE exists, in an agentic mode and a deterministic scanner mode, across seven package ecosystems, and issues findings as SGZ advisories before they reach public CVE databases. The point is what such tools are for: catching authorization flaws in widely embedded libraries early.
Gold Open Source (gold.safeguard.sh, free, no login) shows CVSS, EPSS, KEV status, affected and fixed versions and a recommended safe version, with a free read API and a CI gate GitHub Action. Gold Registry (registry.safeguard.sh, paid) offers hardened drop in components and images held to zero exploitable critical or high CVEs, SLSA L3 or higher and Sigstore signed. We make no claim that Gold holds a patched HAPI FHIR build for these CVEs. With no upstream fix, the habit that matters is knowing which builds carry the library and rebuilding from a patched, signed source as soon as one exists.
Where Safeguard fits
Here is what Safeguard does and does not do for this disclosure.
- Finding the library. Safeguard's dependency scanning reads Maven and Gradle projects, container images and SBOM files and builds a full transitive inventory, so the scan commands in step 1 find
ca.uhn.hapi.fhirartifacts even when something else pulled them in. The platform shows which projects contain a given component and version. - Matching the CVEs. Vulnerability matching will flag affected HAPI versions as the records propagate. Because three records say "all versions," that tells you where the library is, not whether you are exposed. Exposure depends on partitioning, gateway design and interceptors, which a dependency scan cannot see.
- Policies and gates. A policy can flag services carrying HAPI FHIR until the owning team records that the mitigations are in place.
- Writing and testing the mitigation. The Safeguard CLI's assistant can edit code and run commands with your approval: add the
STORAGE_PARTITION_SELECTEDinterceptor, write the negative tests, runmvn verify. The/permissionsmodes (Ask, Accept edits, Plan, Auto, Strict) set how much it does without asking, andsafeguard execruns the same kind of task in CI. - The upgrade later. When a fixed release ships, autonomous remediation can open tested fix pull requests. It ships switched off.
Where Safeguard does not help: it cannot decide your tenant entitlement model, configure your API gateway, or see inside a vendor's hosted FHIR service. For products you buy, the fix must come from the supplier. Nothing here would have prevented these bugs; the value is finding affected services quickly and shipping controls with less friction.
Common mistakes and troubleshooting
- Reading entitlement from the header inside the hook. The header is what the transaction processor overwrites. Use the authenticated identity.
- Testing only plain reads. Many teams test
GET Patient/123across tenants and stop. The override arrives inside a Bundle, so tests must POST transaction and batch Bundles too. - Relying on the hook alone on released versions. Until PR #8404 ships, the hook is skipped for partition selecting requests without a resource type. Block those paths for tenant credentials at the gateway.
- Capping only the compressed body size. A 65 KB body can become 64 MiB.
- Turning off decompression without checking clients. Some integration engines compress large uploads. Check access logs first, or you will break a feed.
- Forgetting the default partition. If the hook refuses it outright, shared terminology lookups may break. Decide explicitly which types and operations may use it.
- Losing the controls during the 9.0.0 upgrade. Major upgrades are when custom interceptors get dropped. Keep the negative tests in CI so the upgrade fails loudly.
FAQ
What is CVE-2026-113874?
It is an incorrect authorization flaw in HAPI FHIR, scored 8.1 by CISA. A caller authorized for one tenant can add a request-partition-ids extension to an entry in a transaction or batch Bundle, and that value replaces the partition the gateway set. The server then reads from or writes to the other tenant's partition, unless a STORAGE_PARTITION_SELECTED entitlement hook blocks it.
Is there a patch for the HAPI FHIR vulnerabilities?
Not for three of them. CISA lists "No fix available" for CVE-2026-113873, CVE-2026-113874 and CVE-2026-113875. For CVE-2026-113876, CISA says "Fixed around September 2026," but the researcher found the change only on master and the 9.0 branch, not in any released version as of 22 October.
Is anyone exploiting these bugs?
No exploitation has been reported. CISA's SSVC notes record exploitation as none, and none of the four CVEs is in the KEV catalog as of 23 October. The researcher has withheld his proof of concept code until fixes ship.
Which HAPI FHIR versions are affected?
The CVE records list all versions. The researcher tested 8.10.0 and found the code paths in v8.8.2, v8.10.1 and v8.12.1, the newest release. The partition extension handler behind CVE-2026-113874 first shipped in v8.2.0, so versions before 8.2.0 do not have that specific code path, though they may have the other three issues.
Am I affected if I do not use partitioning?
Not by CVE-2026-113874, which needs partitioning and header based tenant routing. You may still be affected by the gzip bug, which applies to default configurations, and by the conditional create and subscription bugs if your authorization rules and subscription settings match their prerequisites.
When will HAPI FHIR 9.0.0 ship, and will it fix everything?
The researcher says 9.0.0 is scheduled for 19 November 2026 and is a breaking upgrade to Spring Boot 4, Jackson 3 and Hibernate 7 with no 8.x backport. Based on his source review, the 9.0 branch contains the conditional create change. He found the other three paths unchanged as of 22 October. Check the release notes when it ships.
Does this affect Smile CDR?
Unknown. The researcher reports that Smile CDR releases are based on specific HAPI versions, but he did not test Smile CDR, which has its own modules. CISA lists SmileCDR as the vendor for HAPI FHIR, the open source project. Ask your account contact for a statement on each CVE.
Does Prefer: return=minimal stop the conditional create leak?
No. The client chooses that header, so a caller who wants the body leaves it out. Fix the authorization rules or suppress the body on the server side.
Fix it without waiting for upstream
This disclosure is a clear case for what follows: three of the four HAPI FHIR CVEs have no upstream fix, and the controls that work today are ones your own team ships.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would have helped
None of these demos shows HAPI FHIR. Each shows a real flow that maps onto the work this disclosure asks of a Java team running FHIR.
The first demo is a real Safeguard CLI session. It installs the CLI, opens the interactive terminal and asks it to fix a lodash CVE: the assistant reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, and pushes nothing. For HAPI FHIR you would ask the same assistant to add a STORAGE_PARTITION_SELECTED entitlement interceptor and the negative Bundle tests to your server module, then approve mvn verify before anything runs.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. That is the step that answers "which of our services and images carry ca.uhn.hapi.fhir jars, and which version" across the repositories you already have checked out, including the fat jars where HAPI hides.
Click through it at your own pace, or open it full screen.
The third demo is a real desktop app session. The CLI session shows in the conversation list, you ask for work on your computer, pick the folder, and Approve or Deny each command and file edit; it ends with the upgrade done and tests passing. Here you would point it at the FHIR server repository, ask it to call setUncompressIncomingContents(false) where your clients never compress, and approve the build and test commands one at a time.
Click through it at your own pace, or open it full screen.
To try it on your own code, download Safeguard and follow the CLI documentation.
Quick check
Your multi-tenant HAPI FHIR 8.12.1 server uses RequestHeaderPartitionInterceptor behind a gateway that strips the partition header. Are you protected from CVE-2026-113874?
No. The override comes from a Bundle entry extension, not the header, and 8.12.1 contains the vulnerable handler. Register a STORAGE_PARTITION_SELECTED entitlement interceptor that checks the authenticated caller, and reject the request-partition-ids extension URL at the gateway.
Which of the four HAPI FHIR CVEs can be triggered without authentication?
CVE-2026-113873, the gzip decompression bug. HAPI inflates the request body before AuthorizationInterceptor runs, which is why its CVSS vector says PR:N. Turn off inbound decompression or cap the decompressed size ahead of HAPI.
Sources
- CISA CSAF advisory VA-26-294-01, HAPI FHIR (github.com/cisagov)
- CVE-2026-113874 record (cve.org)
- CVE-2026-113873 record (cve.org)
- CVE-2026-113875 record (cve.org)
- CVE-2026-113876 record (cve.org)
- CVE-2026-113874 in the CVE Services API (cveawg.mitre.org)
- oss-security: HAPI FHIR cross-tenant partition override, authorization bypasses and gzip heap exhaustion (openwall.com)
- Four Authorization and Availability Findings in HAPI FHIR, researcher write-up (abhinavagarwal07.github.io)
- HAPI FHIR releases (github.com/hapifhir)
- Issue #8253: AuthorizationInterceptor does not read-authorize write-operation response bodies (github.com/hapifhir)
- PR #8254: Read authorize patch and conditional create responses (github.com/hapifhir)
- PR #8404: STORAGE_PARTITION_SELECTED is not invoked for partition-selecting operations without a resource type (github.com/hapifhir)
- Partitioning and Multitenancy (hapifhir.io)
- Partition Interceptor Examples (hapifhir.io)
- Authorization Interceptor (hapifhir.io)
- Pointcut javadoc, including STORAGE_PARTITION_SELECTED (hapifhir.io)
- RestfulServer javadoc, setUncompressIncomingContents (hapifhir.io)
- hapi-fhir-base Maven metadata (repo1.maven.org)
- CISA Known Exploited Vulnerabilities catalog feed (cisa.gov)
Last reviewed: 24 October 2026. This is a developing story; check the linked advisories for the latest status.