# OpenMRS ModuleResourcesServlet has Path Traversal that Leads to Arbitrary File Read

Unauthenticated path traversal in OpenMRS ModuleResourcesServlet lets attackers read arbitrary server files like /etc/passwd via crafted module resource paths.

- Payout: Research
- Severity: high
- Program: OpenMRS
- Found by: Arron-bit
- Disclosed: 2026-05-04
- CVE: CVE-2026-40075
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-jjgj-cx3q-pw4w
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-jjgj-cx3q-pw4w
- Tags: area:web domain:web impact:data-leak kind:research platform:ghsa sev:high tech:java technique:legacy-endpoint technique:source-review vuln:info-disclosure vuln:path-traversal

**Target:** Java servlet endpoint /openmrs/moduleResources/{moduleid}
**Root cause:** ModuleResourcesServlet.getFile() concatenates user-controlled pathInfo into a filesystem path without normalize()/startsWith() boundary validation; ModuleUtil.getPathForResource only strips the module ID prefix.
**Steps:**
1. Identify a valid installed module ID (e.g. `legacyui`).
2. Send request to `/openmrs/moduleResources/{moduleid}` with path traversal in pathInfo using `..;` parameter bypass (requires Tomcat < 8.5.31).
3. Server returns HTTP 200 with contents of `/etc/passwd`.
**How found:** Code review of ModuleResourcesServlet.getFile() noting missing normalize/startsWith check, contrasted with correct protection already present in StartupFilter.java.
**Exploitation:** Unauthenticated attacker requests the module resources endpoint with a traversal payload; servlet resolves path outside WEB-INF/view/module and returns arbitrary file contents. Requires Tomcat < 8.5.31 for the `..;` bypass.
**Insight:** When a codebase has one servlet with correct traversal protection (StartupFilter) and another serving similar static resources, diff the two — the unprotected sibling is the bug. Also check container version since Tomcat >=8.5.31 blocks `..;` bypasses.

