Where
-Infinity
0

OpenMRS is an open source electronic medical record system platform. Prior to versions 1.23.0 and 2.10.0, an authenticated user can trigger administrative DWR services. Specifically, the startHl7ArchiveMigration method is accessible, which should be restricted to admin-level accounts. Versions 1.23.0 and 2.10.0 patch the issue.

First published (updated )
Severity
8.2
Path Traversal
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Affected Versions

version ≤ 2.7.8 (latest version at time of disclosure)

https://github.com/openmrs/openmrs-core

Impact

The /openmrs/moduleResources/{moduleid} endpoint in OpenMRS Core is vulnerable to a path traversal attack. The ModuleResourcesServlet does not properly validate user-supplied path input, allowing an attacker to traverse directories and read arbitrary files from the server filesystem (e.g., /etc/passwd, application configuration files containing database credentials).

This endpoint serves static module resources (CSS, JS, images) and is not protected by authentication filters, as these resources are required for rendering the login page. Therefore, this vulnerability can be exploited by an unauthenticated attacker.

Note: Successful exploitation requires the target deployment to run on Apache Tomcat < 8.5.31, where the ..; path parameter bypass is not mitigated by the container. Deployments on Tomcat ≥ 8.5.31 / ≥ 9.0.10 are protected at the container level, though the underlying code defect remains.

Steps to Reproduce

1. Identify a valid installed module ID on the target OpenMRS instance (e.g., legacyui). 2. Send the following HTTP request:

<img width="1038" height="798" alt="image" src="https://github.com/user-attachments/assets/7d10ee0e-4d81-4c01-bc84-a1bf5715f170" />

3. The server responds with HTTP 200 and the contents of /etc/passwd:

<img width="1028" height="843" alt="image" src="https://github.com/user-attachments/assets/b6806a7e-ff52-4f51-8f7f-7ea4e9754d10" />

Root Cause Analysis

The vulnerability exists in ModuleResourcesServlet.java (web/src/main/java/org/openmrs/module/web/ModuleResourcesServlet.java).

The getFile() method constructs a filesystem path from user-controlled input without performing path boundary validation:

java protected File getFile(HttpServletRequest request) { // Step 1: User-controlled path input String path = request.getPathInfo();

// Step 2: Extract module from path prefix Module module = ModuleUtil.getModuleForPath(path); if (module == null) { return null; }

// Step 3: Strip module ID prefix — no traversal check String relativePath = ModuleUtil.getPathForResource(module, path);

// Step 4: Concatenate into absolute path String realPath = getServletContext().getRealPath("") + MODULEPATH + module.getModuleIdAsPath() + "/resources" + relativePath; // contains "/../../../etc/passwd"

realPath = realPath.replace("/", File.separator);

// Step 5: No normalize().startsWith() boundary check File f = new File(realPath); if (!f.exists()) { return null; }

return f; // Arbitrary file returned to client }

The helper method ModuleUtil.getPathForResource() only strips the module ID prefix and performs no sanitization:

java public static String getPathForResource(Module module, String path) { if (path.startsWith("/")) { path = path.substring(1); } return path.substring(module.getModuleIdAsPath().length()); // Returns unsanitized remainder, e.g., "/../../../../../../etc/passwd" }

The resulting path resolves as:

{webapp}/WEB-INF/view/module/legacyui/resources/../../../../../../etc/passwd → /etc/passwd

Notably, the same codebase already implements correct path traversal protection in StartupFilter.java:

java // StartupFilter.java — correct protection fullFilePath = fullFilePath.resolve(httpRequest.getPathInfo()); if (!(fullFilePath.normalize().startsWith(filePath))) { log.warn("Detected attempted directory traversal..."); return; // Request rejected }

This check is absent from ModuleResourcesServlet.

Remediation

Add a path boundary check after constructing realPath and before returning the File object. The fix should use normalize() + startsWith() to ensure the resolved path stays within the allowed module resources directory:

java File f = new File(realPath); Path allowedBase = Paths.get(getServletContext().getRealPath(""), "WEB-INF", "view", "module"); if (!f.toPath().normalize().startsWith(allowedBase.normalize())) { log.warn("Blocked path traversal attempt: {}", request.getPathInfo()); return null; }

This is consistent with the existing pattern used in StartupFilter.java and TestInstallUtil.java within the same project.

1 / 2
Source: GitHub
First published (updated )
Severity
4.8
EPSS
0.03%
XSS
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N

A stored cross-scripting (XSS) vulnerability in Openmrs v2.4.3 Build 0ff0ed allows attackers to execute arbitrary web scripts or HTML via injecting a crafted payload into the personName.middleName parameter at /openmrs/admin/patients/shortPatientForm.form.

First published (updated )
Severity
6.8
EPSS
0.02%
CSRF
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H

A Cross-Site Request Forgery (CSRF) in Openmrs 2.4.3 Build 0ff0ed allows attackers to execute arbitrary operations via a crafted GET request.

First published (updated )
Severity
5.4
EPSS
0.03%
XSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

A reflected cross-site scripting (XSS) vulnerability in the component /legacyui/quickReportServlet of Openmrs 2.4.3 Build 0ff0ed allows attackers to execute arbitrary JavaScript in the context of a user's browser via a crafted payload injected into the reportType parameter.

First published (updated )
Severity
8
EPSS
0.03%
CSRF
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H

A Cross-Site Request Forgery (CSRF) in the component /admin/users/user.form of Openmrs 2.4.3 Build 0ff0ed allows attackers to execute arbitrary operations via a crafted request. In this case, an attacker could elevate a low-privileged account to an administrative role by leveraging the CSRF vulnerability at the /admin/users/user.form endpoint.

First published (updated )
Severity
8.8
XSS, CSRF
CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

The Reporting Module 1.12.0 for OpenMRS allows CSRF attacks with resultant XSS, in which administrative authentication is hijacked to insert JavaScript into a name field in webapp/reports/manageReports.jsp.

First published (updated )
Severity
9.4
Path Traversal
AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:N

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.allowwebadmin 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

1. Construct a malicious .omod file (which is a ZIP/JAR archive) containing a ZIP entry with a path traversal payload in its entry name, such as web/module/../../../../<targetfilename>. Upload this file to POST /openmrs/ws/rest/v1/module with 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" />

2. The server parses and loads the module. During WebModuleUtil.startModule(), entries under web/module/ are automatically extracted. The existing check Paths.get(name).startsWith("..") only blocks entries beginning with .., so an entry starting with web/module/ passes the check. The ../ sequences in the remaining path cause the file to be written outside the intended WEB-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" />

3. 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:

java 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():

java // ✅ Correct — uses normalize().startsWith() if (!parent.toPath().normalize().startsWith(docBase)) { throw new UnsupportedOperationException("..."); }

TestInstallUtil.addZippedTestModules():

java // ✅ 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.allowwebadmin

The module.allowwebadmin 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 write

Remediation

Add normalize().startsWith() boundary validation before writing, consistent with the existing pattern in ModuleUtil.expandJar():

java 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.allowwebadmin restriction consistently across all module upload entry points, including the REST API.

1 / 2
Source: GitHub
First published (updated )
Severity
8
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

openmrs-module-fhir2 provides the FHIR REST API and related services for OpenMRS, an open medical records system. In versions of the FHIR2 module prior to 2.5.0, privileges were not always correctly checked, which means that unauthorized users may have been able to add or edit data they were not supposed to be able to. All implementers should update to FHIR2 2.5.0 or newer as soon as is feasible to receive a patch.

First published (updated )
Severity
7.5
Path Traversal
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

OpenMRS is a patient-based medical record system focusing on giving providers a free customizable electronic medical record system. Affected versions are subject to arbitrary file exfiltration due to failure to sanitize request when satisfying GET requests for /images & /initfilter/scripts. This can allow an attacker to access any file on a system running OpenMRS that is accessible to the user id OpenMRS is running under. Affected implementations should update to the latest patch version of OpenMRS Core for the minor version they use. These are: 2.1.5, 2.2.1, 2.3.5, 2.4.5 and 2.5.3. As a general rule, this vulnerability is already mitigated by Tomcat's URL normalization in Tomcat 7.0.28+. Users on older versions of Tomcat should consider upgrading their Tomcat instance as well as their OpenMRS instance.

First published (updated )
Severity
5.4
XSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

A vulnerability was found in OpenMRS Appointment Scheduling Module up to 1.12.x. It has been classified as problematic. This affects the function validateFieldName of the file api/src/main/java/org/openmrs/module/appointmentscheduling/validator/AppointmentTypeValidator.java. The manipulation leads to cross site scripting. It is possible to initiate the attack remotely. Upgrading to version 1.13.0 is able to address this issue. The name of the patch is 34213c3f6ea22df427573076fb62744694f601d8. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-216915.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

A vulnerability, which was classified as problematic, was found in OpenMRS Appointment Scheduling Module up to 1.16.x. This affects the function getNotes of the file api/src/main/java/org/openmrs/module/appointmentscheduling/AppointmentRequest.java of the component Notes Handler. The manipulation of the argument notes leads to cross site scripting. It is possible to initiate the attack remotely. Upgrading to version 1.17.0 is able to address this issue. The name of the patch is 2ccbe39c020809765de41eeb8ee4c70b5ec49cc8. It is recommended to upgrade the affected component. The identifier VDB-216741 was assigned to this vulnerability.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

A vulnerability was found in OpenMRS Admin UI Module up to 1.4.x. It has been rated as problematic. This issue affects some unknown processing of the file omod/src/main/webapp/pages/metadata/privileges/privilege.gsp of the component Manage Privilege Page. The manipulation leads to cross site scripting. The attack may be initiated remotely. Upgrading to version 1.5.0 is able to address this issue. The name of the patch is 4f8565425b7c74128dec9ca46dfbb9a3c1c24911. It is recommended to upgrade the affected component. The identifier VDB-216917 was assigned to this vulnerability.

First published (updated )
Severity
9.8
XEE
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

An XML External Entity (XXE) vulnerability exists in HTML Form Entry 3.7.0, as distributed in OpenMRS Reference Application 2.8.0.

First published (updated )
Severity
4.3
XSS
AV:N/AC:M/Au:N/C:N/I:P/A:N

Multiple cross-site scripting (XSS) vulnerabilities in OpenMRS 2.1 Standalone Edition allow remote attackers to inject arbitrary web script or HTML via the (1) givenName, (2) familyName, (3) address1, or (4) address2 parameter to registrationapp/registerPatient.page; the (5) comment parameter to allergyui/allergy.page; the (6) w10 parameter to htmlformentryui/htmlform/enterHtmlForm/submit.action; the (7) HTTP Referer Header to login.htm; the (8) returnUrl parameter to htmlformentryui/htmlform/enterHtmlFormWithStandardUi.page or (9) coreapps/mergeVisits.page; or the (10) visitId parameter to htmlformentryui/htmlform/enterHtmlFormWithSimpleUi.page.

First published (updated )
Severity
6.8
CSRF
AV:N/AC:M/Au:N/C:P/I:P/A:P

Cross-site request forgery (CSRF) vulnerability in OpenMRS 2.1 Standalone Edition allows remote attackers to hijack the authentication of administrators for requests that add a new user via a Save User action to admin/users/user.form.

First published (updated )
Severity
4
AV:N/AC:L/Au:S/C:P/I:N/A:N

The administration module in OpenMRS 2.1 Standalone Edition allows remote authenticated users to obtain read access via a direct request to /admin.

First published (updated )
Severity
9.8
Input Validation
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

OpenMRS openmrs-module-htmlformentry 3.3.2 is affected by: (Improper Input Validation).

First published (updated )
Severity
10
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

The Reporting Compatibility Add On before 2.0.4 for OpenMRS, as distributed in OpenMRS Reference Application before 2.6.1, does not authenticate users when deserializing XML input into ReportSchema objects. The result is that remote unauthenticated users are able to execute operating system commands by crafting malicious XML payloads, as demonstrated by a single admin/reports/reportSchemaXml.form request.

First published (updated )
Severity
10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

OpenMRS before 2.24.0 is affected by an Insecure Object Deserialization vulnerability that allows an unauthenticated user to execute arbitrary commands on the targeted system via crafted XML data in a request body.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

A vulnerability classified as problematic has been found in OpenMRS Admin UI Module up to 1.4.x. Affected is the function sendErrorMessage of the file omod/src/main/java/org/openmrs/module/adminui/page/controller/systemadmin/accounts/AccountPageController.java of the component Account Setup Handler. The manipulation leads to cross site scripting. It is possible to launch the attack remotely. Upgrading to version 1.5.0 is able to address this issue. The name of the patch is 702fbfdac7c4418f23bb5f6452482b4a88020061. It is recommended to upgrade the affected component. VDB-216918 is the identifier assigned to this vulnerability.

First published (updated )
Severity
8.8
Path Traversal
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

A remote code execution (RCE) vulnerability was discovered in the htmlformentry (aka HTML Form Entry) module before 3.11.0 for OpenMRS. By leveraging path traversal, a malicious Velocity Template Language file could be written to a directory. This file could then be accessed and executed.

First published (updated )
Severity
6.1
Input Validation, XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

OpenMRS 2.9 and prior copies "Referrer" header values into an html element named "redirectUrl" within many webpages (such as login.htm). There is insufficient validation for this parameter, which allows for the possibility of cross-site scripting.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

In OpenMRS 2.9 and prior, the UI Framework Error Page reflects arbitrary, user-supplied input back to the browser, which can result in XSS. Any page that is able to trigger a UI Framework Error is susceptible to this issue.

First published (updated )
Severity
6.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

In OpenMRS 2.9 and prior, he import functionality of the Data Exchange Module does not properly redirect to a login page when an unauthenticated user attempts to access it. This allows unauthenticated users to use a feature typically restricted to administrators.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

In OpenMRS 2.9 and prior, the app parameter for the ActiveVisit's page is vulnerable to cross-site scripting.

First published (updated )
Severity
6.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

In OpenMRS 2.9 and prior, the export functionality of the Data Exchange Module does not properly redirect to a login page when an unauthenticated user attempts to access it. This allows the export of potentially sensitive information.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

In OpenMRS 2.9 and prior, the sessionLocation parameter for the login page is vulnerable to cross-site scripting.

First published (updated )
Severity
9.8
SQL Injection
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

An SQL Injection vulnerability exists in OpenMRS Reference Application Standalone Edition <=2.11 and Platform Standalone Edition <=2.4.0 via GET requests on arbitrary parameters in patient.page.

First published (updated )
Severity
6.1
XSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

A vulnerability classified as problematic has been found in OpenMRS HTML Form Entry UI Framework Integration Module up to 1.x. This affects an unknown part. The manipulation leads to cross site scripting. It is possible to initiate the attack remotely. Upgrading to version 2.0.0 is able to address this issue. The name of the patch is 811990972ea07649ae33c4b56c61c3b520895f07. It is recommended to upgrade the affected component. The identifier VDB-216873 was assigned to this vulnerability.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203