OpenMRS Core CVE-2026-40076
CRITICALAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
ReconCompromise admin credentials
-
DeliveryAuthenticate to REST API via Basic Auth
-
ExploitUpload malicious .omod with traversal payload
-
InstallTrigger WebModuleUtil.startModule() extraction
-
C2Write JSP webshell to Tomcat webroot
-
ExecuteAccess deployed JSP via HTTP
-
ImpactExecute arbitrary code as Tomcat user
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling Path canonicalization, traversal prevention
MITRE ATT&CK
2 techniques across 2 tactics: Discovery, Collection The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Requires valid OpenMRS administrator credentials with privileges to access the REST API endpoint POST /openmrs/ws/rest/v1/module (CVSS PR:H). Specifically, the attacker must possess an account in the System Developer or Administrator role capable of invoking module management operations via Basic Authentication. The vulnerability affects default configurations of OpenMRS Core versions ≤ 2.7.8 and 2.8.0-2.8.5 deployed on Apache Tomcat where the REST API is enabled (standard deployment). No special server-side feature enablement or non-default configuration required beyond having an accessible REST API endpoint. The module.allow_web_admin property, if set to false, does NOT limit exploitation because the REST API bypasses this control. Exploitation requires network access to the OpenMRS instance, but does NOT require user interaction (CVSS UI:N). Attack is automatable once credentials are obtained. Limiting factors: Attacker must first compromise high-privilege credentials through separate means (phishing, brute force, credential theft, insider threat). The vulnerability cannot be exploited by low-privilege authenticated users or unauthenticated attackers. Organizations using strong MFA on admin accounts, restricting REST API access via firewall rules, or disabling web-based module upload reduce exploitability significantly. |
| Impact | CVSS 8.7 (High/Critical borderline) with network attack vector (AV:N), low complexity (AC:L), and Changed scope (S:C) indicates significant exploitability once attacker gains high privileges (PR:H). However, real-world risk is constrained by the authentication requirement - attacker must possess valid administrator credentials to access POST /openmrs/ws/rest/v1/module. No EPSS score provided, and no CISA KEV listing indicates this is not confirmed actively exploited in the wild. Public exploit code exists in the form of detailed GitHub advisory with proof-of-concept screenshots and crafted .omod construction instructions, lowering the technical barrier for authenticated adversaries. The Changed scope amplifies impact beyond confidentiality/integrity to potential compromise of the underlying Tomcat container. Critical risk factors: (1) healthcare context - OpenMRS manages sensitive patient data protected by regulations like HIPAA; (2) bypass of module.allow_web_admin control suggests defense-in-depth failures; (3) no patch available for either affected version range per GitHub advisory data. Risk is elevated for installations with compromised or weak admin credentials, insider threats, or supply chain attack scenarios. However, the PR:H requirement means this is not a mass-exploitation vector - prioritize based on administrative access controls and monitoring posture. |
| Exploit ScenarioDerived | An attacker with compromised OpenMRS administrator credentials (obtained via phishing, credential stuffing, or insider access) authenticates to the REST API and uploads a malicious .omod module archive via POST /openmrs/ws/rest/v1/module. The crafted archive contains a ZIP entry named web/module/resources/../../../../shell.jsp embedding a JSP webshell payload. The incomplete path validation allows the file to traverse outside WEB-INF/view/module/ and write to /usr/local/tomcat/webapps/openmrs/shell.jsp in the Tomcat webroot. The attacker then accesses https://target-openmrs.hospital.org/openmrs/shell.jsp in a browser, triggering server-side execution of the JSP and achieving remote code execution as the Tomcat user. From there, the attacker pivots to exfiltrate patient health records, install persistence mechanisms, or compromise other systems on the hospital network. Public proof-of-concept with screenshots exists in the GitHub advisory, making exploitation straightforward for adversaries with admin access. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – May 04, 2026
Path traversal (Zip Slip) vulnerability in OpenMRS Core ≤ 2.7.8 and 2.8.0-2.8.5 allows authenticated administrators to achieve remote code execution by uploading a malicious .omod module archive to the REST API endpoint POST /openmrs/ws/rest/v1/module. Attackers can write arbitrary JSP files to the Tomcat webroot via crafted ZIP entries containing directory traversal sequences (e.g., web/module/../../../../malicious.jsp), which bypass incomplete path validation in WebModuleUtil.startModule(). The vulnerability also bypasses the module.allow_web_admin security control, as the REST API does not enforce this restriction despite Legacy UI being protected. No vendor-released patch identified at time of analysis for either affected version range.
RemediationAI
No vendor-released patch identified at time of analysis for either affected version range (≤ 2.7.8 or 2.8.0-2.8.5). OpenMRS community advisory at https://github.com/openmrs/openmrs-core/security/advisories/GHSA-78fc-9688-w8xw recommends applying normalize().startsWith() boundary validation in WebModuleUtil.startModule() before writing extracted files, consistent with the pattern already used in ModuleUtil.expandJar(). Until a patched release is available, implement compensating controls: (1) Disable the REST API module upload endpoint POST /openmrs/ws/rest/v1/module at the reverse proxy or servlet filter level - trade-off is administrators must use CLI or filesystem-based module deployment; (2) Enforce strict module.allow_web_admin=false in runtime properties AND patch the REST API to honor this property by adding the allowAdmin() check before calling ModuleFactory.loadModule() - note this only prevents upload via web, not exploitation if malicious modules already exist; (3) Restrict administrative access to the REST API using network segmentation, IP allowlisting, or mutual TLS to minimize attack surface - does not prevent insider threats or credential compromise; (4) Enable Tomcat SecurityManager with strict file write permissions to prevent writes outside WEB-INF/view/module/ - may break legitimate module functionality and requires extensive testing. Monitor for suspicious .omod uploads and unexpected JSP files in webroot using file integrity monitoring. Patching guidance in advisory suggests adding outFile.toPath().normalize().startsWith(Paths.get(realPath, "WEB-INF").normalize()) check before FileOutputStream instantiation.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in maven
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
OpenMRS (Open Medical Record System) is a Java-based electronic health record platform commonly deployed on Apache Tomcat. The vulnerability resides in the module upload functionality that processes .omod files (custom ZIP/JAR archives containing OpenMRS plugins). CWE-22 (Path Traversal) manifests here because WebModuleUtil.startModule() performs an incomplete boundary check using Paths.get(name).startsWith(".."), which only blocks entries beginning with literal ".." but fails to detect traversal sequences embedded after a valid prefix like "web/module/". After substring extraction, the filepath is concatenated directly into the output path without normalization, allowing an attacker to write files outside the intended WEB-INF/view/module/ directory. Ironically, other extraction methods in the same codebase (ModuleUtil.expandJar(), TestInstallUtil.addZippedTestModules()) correctly implement normalize().startsWith() boundary checks, making this a localized oversight rather than a systematic design flaw. The Maven package org.openmrs.web:openmrs-web (confirmed by CPE data) is affected in two version ranges: legacy versions ≤ 2.7.8 and newer versions 2.8.0-2.8.5.
Know when Tomcat gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
Lifecycle Timeline
3DescriptionGitHub Advisory
Affected Versions
version ≤ 2.7.8 (latest version at time of disclosure)
https://github.com/openmrs/openmrs-core
Impact
The endpoint POST /openmrs/ws/rest/v1/module is vulnerable to a path traversal (Zip Slip) attack. An authenticated attacker can upload a crafted .omod archive containing ZIP entries with directory traversal sequences. Upon automatic extraction by the server, the incomplete path validation in WebModuleUtil.startModule() fails to prevent entries such as web/module/../../../../malicious.jsp from being written outside the intended module directory. If the traversal target falls within the web application root (e.g., /usr/local/tomcat/webapps/openmrs/), the attacker achieves arbitrary file write and subsequent Remote Code Execution.
Notably, other extraction methods in the same codebase (ModuleUtil.expandJar(), TestInstallUtil.addZippedTestModules()) are properly protected with normalize().startsWith() checks - this vulnerability is an oversight where the same fix was not applied.
Furthermore, the module.allow_web_admin runtime property, which is intended to restrict administrators from managing modules via the web interface, only gates the Legacy UI controller entry point. The REST API endpoint POST /openmrs/ws/rest/v1/module does not check this property, allowing this restriction to be fully bypassed.
Steps to Reproduce
- Construct a malicious
.omodfile (which is a ZIP/JAR archive) containing a ZIP entry with a path traversal payload in its entry name, such asweb/module/../../../../<target_filename>. Upload this file toPOST /openmrs/ws/rest/v1/modulewith valid admin credentials via Basic Auth.
<img width="1986" height="1102" alt="image" src="https://github.com/user-attachments/assets/647f15de-7e8c-40b9-aba9-d4db5d2e0b52" />
<img width="2048" height="1078" alt="image" src="https://github.com/user-attachments/assets/301412a0-e3b0-4afb-91c2-e9739de3080d" />
- The server parses and loads the module. During
WebModuleUtil.startModule(), entries underweb/module/are automatically extracted. The existing checkPaths.get(name).startsWith("..")only blocks entries beginning with.., so an entry starting withweb/module/passes the check. The../sequences in the remaining path cause the file to be written outside the intendedWEB-INF/view/module/directory - for example, into the web application root at/usr/local/tomcat/webapps/openmrs/.
<img width="1439" height="141" alt="image" src="https://github.com/user-attachments/assets/4bda3b1e-a80e-42ed-af2b-a1da53e8db03" />
- The traversed file is now accessible under the web application root. If the written file is a JSP script, accessing it via the browser triggers server-side execution, achieving RCE.
<img width="1482" height="300" alt="image" src="https://github.com/user-attachments/assets/61936002-78cd-4203-80f0-f0a8702b216c" />
Root Cause Analysis
The vulnerability exists in WebModuleUtil.startModule() (web/src/main/java/org/openmrs/module/web/WebModuleUtil.java).
Vulnerable code:
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
// ❌ Incomplete check - only blocks entries starting with ".."
if (Paths.get(name).startsWith("..")) {
throw new UnsupportedOperationException("...");
}
if (name.startsWith("web/module/")) {
String filepath = name.substring(11);
StringBuilder absPath = new StringBuilder(realPath + "/WEB-INF");
absPath.append("/view/module/");
absPath.append(mod.getModuleIdAsPath()).append("/").append(filepath);
// ❌ No normalize() or startsWith() boundary check before writing
File outFile = new File(absPath.toString().replace("/", File.separator));
outStream = new FileOutputStream(outFile, false);
inStream = jarFile.getInputStream(entry);
OpenmrsUtil.copyFile(inStream, outStream);
}
}Why the check fails: For an entry named web/module/foo/../../../../evil.jsp, Paths.get(name) starts with web, not .., so the check passes. After name.substring(11), the filepath foo/../../../../evil.jsp is concatenated directly into the output path without normalization, resulting in a write outside the intended directory.
Correctly protected code in the same codebase:
ModuleUtil.expandJar():
// ✅ Correct - uses normalize().startsWith()
if (!parent.toPath().normalize().startsWith(docBase)) {
throw new UnsupportedOperationException("...");
}TestInstallUtil.addZippedTestModules():
// ✅ Correct - uses normalize().startsWith()
if (!zipEntryFile.toPath().normalize().startsWith(moduleRepository.toPath().normalize())) {
throw new IOException("Bad zip entry");
}The fix pattern is already known and applied elsewhere in the codebase. WebModuleUtil.startModule() is an oversight.
Bypass of module.allow_web_admin
The module.allow_web_admin property only restricts module operations at the Legacy UI layer (ModuleListController). The REST API endpoint does not consult this property:
Legacy UI: POST /admin/modules/moduleList.form → allowAdmin() check → [BLOCKED]
REST API: POST /ws/rest/v1/module → No allowAdmin() check → [ALLOWED]
↓
ModuleFactory.loadModule()
↓
WebModuleUtil.startModule() ← Zip Slip here, no allowAdmin check
↓
FileOutputStream.write() ← Arbitrary file writeRemediation
Add normalize().startsWith() boundary validation before writing, consistent with the existing pattern in ModuleUtil.expandJar():
File outFile = new File(absPath.toString().replace("/", File.separator));
// ✅ Add this check
if (!outFile.toPath().normalize().startsWith(
Paths.get(realPath, "WEB-INF").normalize())) {
throw new UnsupportedOperationException(
"Zip entry '" + name + "' would be written outside the allowed directory.");
}Additionally, enforce the module.allow_web_admin restriction consistently across all module upload entry points, including the REST API.
Executive ViewAI
OpenMRS Core versions 2.7.8 and 2.8.0-2.8.5 contain a critical remote code execution vulnerability allowing authenticated administrators to upload malicious modules that execute arbitrary code on the server. Organizations running affected versions face immediate risk of complete system compromise through the administrative REST API, requiring urgent action to restrict module upload capabilities or upgrade to patched releases.
No vendor-released patch identified at time of analysis. Interim mitigations: (1) Disable REST API module upload endpoint via application configuration or reverse proxy rules; (2) Implement network-level access controls restricting POST /openmrs/ws/rest/v1/module to defined administrative IP ranges only; (3) Enforce multi-factor authentication for all administrative accounts; (4) Monitor Tomcat webroot and application logs for unexpected JSP file creation or execution; (5) Review module.allow_web_admin security control enforcement across Legacy UI and REST API parity; (6) Maintain offline backups of core application directories to enable rapid recovery if compromise is detected.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Path traversal exploits occur when applications use user-controlled input to construct file system paths without proper validation.
Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.
Affected Products (CPE)GitHub Advisory
When running Apache Tomcat versions 9.0.0.M1 to 9.0.0, 8.5.0 to 8.5.22, 8.0.0.RC1 to 8.0.46 and 7.0.0 to 7.0.81 with HTT
When using the Apache JServ Protocol (AJP), care must be taken when trusting incoming connections to Apache Tomcat. Rate
In SysAid On-Premise before 23.3.36, a path traversal vulnerability leads to code execution after an attacker writes a f
Remote code execution is possible with Apache Tomcat before 6.0.48, 7.x before 7.0.73, 8.x before 8.0.39, 8.5.x before 8
When running Apache Tomcat 7.0.0 to 7.0.79 on Windows with HTTP PUTs enabled (e.g. Rated high severity (CVSS 8.1), this
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
MultipartStream.java in Apache Commons FileUpload before 1.3.1, as used in Apache Tomcat, JBoss Web, and other products,
The payload length in a WebSocket frame was not correctly validated in Apache Tomcat 10.0.0-M1 to 10.0.0-M6, 9.0.0.M1 to
When the default servlet in Apache Tomcat versions 9.0.0.M1 to 9.0.11, 8.5.0 to 8.5.33 and 7.0.23 to 7.0.90 returned a r
The documentation of Apache Tomcat 10.1.0-M1 to 10.1.0-M14, 10.0.0-M1 to 10.0.20, 9.0.13 to 9.0.62 and 8.5.38 to 8.5.78
When using a VirtualDirContext with Apache Tomcat 7.0.0 to 7.0.80 it was possible to bypass security constraints and/or
When using Apache Tomcat versions 10.0.0-M1 to 10.0.0-M4, 9.0.0.M1 to 9.0.34, 8.5.0 to 8.5.54 and 7.0.0 to 7.0.103 if a)
GHSA-78fc-9688-w8xw
NVD
CVE.org
EPSS
Exploit-DB