FHIR Validator: Unauthenticated Blind SSRF via /loadIG Endpoint Enables Internal Network Probing
Date: 2026-03
Affected: maven/ca.uhn.hapi.fhir:org.hl7.fhir.core
Attack vector: ssrf
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-34360
CWE: CWE-918
CVSS: 5.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N)

## Summary The `/loadIG` HTTP endpoint in the FHIR Validator HTTP service accepts a user-supplied URL via JSON body and makes server-side HTTP requests to it without any hostname, scheme, or domain validation. An unauthenticated attacker with network access to the validator can probe internal network services, cloud metadata endpoints, and map network topology through error-based information leakage. With `explore=true` (the default for this code path), each request triggers multiple outbound HTTP calls, amplifying reconnaissance capability. ## Details **Root cause chain:** 1. `LoadIGHTTPHandler.handle()` reads the `ig` field from user-supplied JSON and passes it directly to `IgLoader.loadIg()` with no validation: ```java // LoadIGHTTPHandler.java:35,43 String ig = wrapper.asString("ig"); engine.getIgLoader().loadIg(engine.getIgs(), engine.getBinaries(), ig, false); ``` 2. `loadIg()` calls `loadIgSource(srcPackage, recursive, true)` with `explore=true` (IgLoader.java:153). 3. `loadIgSource()` checks `Common.isNetworkPath(src)` which only verifies the URL starts with `http:` or `https:` — no host/IP validation (Common.java:14-16). 4. The URL reaches `ManagedWebAccess.get()` which calls `inAllowedPaths()`. This check is a no-op by default because `allowedDomains` is initialized as an empty list, and the code explicitly returns `true` when empty: ```java // ManagedWebAccess.java:104-106 static boolean inAllowedPaths(String pathname) { if (allowedDomains.isEmpty()) {


Mitigations:

Architectural layers (MAESTRO):