Critical Alert 4 Active Exploits Detected Today

CVE-2026-48908 JoomShaper SP Page Builder Unrestricted Upload of File with Dangerous Type Vulnerability →
CVE-2026-55255 Langflow Authorization Bypass Through User-Controlled Key Vulnerability →
CVE-2026-56290 Joomlack Page Builder Improper Access Control Vulnerability →
CVE-2026-48282 Adobe ColdFusion Path Traversal Vulnerability →
Powered by CVE Watchtower
×

CVE Watchtower


← Back to CVE List

CVE-2026-40075NVD

Vulnerability Summary

## 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("")
+ MODULE_PATH
+ 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.
Severity Level
HIGH(7.5)
Published Date
May 4, 2026
Last Modified
May 8, 2026
Exploitation Status
No confirmed exploitation yet
EPSS Score (30-Day)
0.10%Probability
Root Weakness (CWE)
N/A
CVSS v3.1 Base Metrics
Attack VectorNetwork
Attack ComplexityLow
Privileges RequiredNone
User InteractionNone
ScopeUnchanged
ConfidentialityHigh
IntegrityNone
AvailabilityNone

External References