Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-10595

CVE-2026-10595: Lollms Path Traversal Vulnerability

CVE-2026-10595 is a path traversal flaw in parisneo/lollms that allows unauthenticated attackers to read arbitrary files using URL-encoded sequences. This post covers technical details, affected versions, and mitigations.

Published:

CVE-2026-10595 Overview

CVE-2026-10595 is a path traversal vulnerability [CWE-23] in parisneo/lollms version 2.1.0. The flaw resides in the Single Page Application (SPA) catch-all route implemented in backend/routers/ui.py. User-controlled path input is joined directly into a filesystem path without sanitization or containment checks. URL-encoded dot-dot sequences (%2e%2e) bypass Starlette's built-in path normalization and are resolved by Python's pathlib. An unauthenticated remote attacker can read arbitrary files on the server hosting the application. The issue has been resolved in version 3.

Critical Impact

Unauthenticated attackers can read arbitrary files on the server, including configuration files, source code, and credentials, over the network with no user interaction.

Affected Products

  • parisneo/lollms version 2.1.0
  • Earlier versions in the 2.x branch sharing the same SPA route implementation
  • Fixed in parisneo/lollms version 3

Discovery Timeline

  • 2026-08-09 - CVE-2026-10595 published to the National Vulnerability Database (NVD)
  • 2026-08-10 - Last updated in NVD database

Technical Details for CVE-2026-10595

Vulnerability Analysis

The vulnerable code registers a FastAPI catch-all route that maps any unmatched request path to a file under a static directory. The handler concatenates the full_path parameter to STATIC_DIR using pathlib and serves the resulting file if it exists. No check confirms that the resolved path stays within STATIC_DIR.

Starlette normalizes plain ../ sequences before routing. However, percent-encoded variants such as %2e%2e%2f are not normalized at the routing layer. When pathlib later resolves the joined path, it interprets the decoded dot-dot segments and escapes the intended directory. The result is arbitrary file read on the host filesystem with the privileges of the application process.

Root Cause

The root cause is missing containment validation between the resolved user path and the base static directory. The original handler trusted Starlette to strip traversal sequences, but Starlette's normalization does not cover URL-encoded separators. Combined with pathlib's automatic resolution of .., this creates a classic Relative Path Traversal condition classified under [CWE-23].

Attack Vector

An attacker sends an HTTP GET request to the application with a crafted path containing URL-encoded traversal sequences, for example /%2e%2e/%2e%2e/etc/passwd. The request requires no authentication or user interaction. The server resolves the path outside of STATIC_DIR and returns the file contents in the HTTP response. Sensitive targets include application configuration files, private keys, database files, and environment variables.

python
     # 3. SPA Catch-All
     @app.get("/{full_path:path}", include_in_schema=False)
     async def serve_vue_app(full_path: str):
-        # Resolve path against dist
-        path = STATIC_DIR / full_path
+        # Resolve path against dist and prevent path traversal
+        resolved_static = STATIC_DIR.resolve()
+        path = (STATIC_DIR / full_path).resolve()
+
+        if not path.is_relative_to(resolved_static):
+            raise HTTPException(status_code=404, detail="Asset not found")
 
         # If it's a physical file in dist root (e.g. favicon.ico, robots.txt), serve it
         if path.exists() and path.is_file():

Source: GitHub Commit 9bc6431 — the patch resolves both paths, then rejects any request whose resolved target is not relative to STATIC_DIR.

Detection Methods for CVE-2026-10595

Indicators of Compromise

  • HTTP request paths containing URL-encoded traversal sequences such as %2e%2e%2f, %2e%2e/, or ..%2f against lollms endpoints
  • Successful HTTP 200 responses to requests targeting paths outside the SPA static directory
  • Access log entries returning non-HTML content types for unusual paths served by the catch-all route
  • Outbound retrieval of sensitive files such as /etc/passwd, .env, or private keys through the web port

Detection Strategies

  • Deploy web application firewall (WAF) rules that decode and inspect URL parameters for traversal patterns before routing
  • Alert on lollms access logs where the request path contains %2e, %2f, or .. after URL decoding
  • Correlate anomalous file-size responses from the SPA catch-all route with client IP reputation data
  • Baseline expected static asset paths and flag deviations from that allowlist

Monitoring Recommendations

  • Enable verbose HTTP access logging on all lollms deployments and forward logs to a centralized analytics platform
  • Monitor process-level file access on the lollms host for reads outside the application's static directory
  • Track authentication-free routes for spikes in request volume or entropy in path parameters
  • Review egress traffic for large or unexpected responses originating from the lollms service

How to Mitigate CVE-2026-10595

Immediate Actions Required

  • Upgrade parisneo/lollms to version 3 or later, which contains the containment check in backend/routers/ui.py
  • Restrict network exposure of lollms instances to trusted networks or behind an authenticated reverse proxy until patched
  • Audit web server access logs for URL-encoded traversal attempts and validate whether any succeeded
  • Rotate any credentials, tokens, or keys that were readable from the application host if exploitation is suspected

Patch Information

The fix is available in the upstream commit 9bc6431 and shipped in parisneo/lollms version 3. The patch calls .resolve() on both the base static directory and the joined user path, then uses path.is_relative_to(resolved_static) to reject any request that escapes the intended directory with an HTTP 404 response. Additional context is available in the Huntr bounty report.

Workarounds

  • Place lollms behind a reverse proxy such as nginx and reject requests whose decoded path contains .. segments
  • Apply a WAF rule that blocks URL-encoded traversal patterns (%2e%2e, %252e) before they reach the FastAPI application
  • Run the lollms process under a low-privilege system account with filesystem access limited to the application directory
  • Use mandatory access control (AppArmor, SELinux) to constrain readable paths for the lollms service
bash
# Example nginx snippet to reject encoded traversal before it reaches lollms
location / {
    if ($request_uri ~* "(\.\./|%2e%2e|%252e%252e)") {
        return 404;
    }
    proxy_pass http://127.0.0.1:9600;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.