T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/mcp-server.js:117
- Finding
- Unrestricted Local File Disclosure Through MCP Resource Handlers## Vulnerability Details **File Location**: `scripts/mcp-server.js`, lines 117–121, 166–190 **Vulnerability Type**: Arbitrary local file read and directory traversal **Risk Level**: High ### Vulnerable Code ```javascript { uriTemplate: 'file://{path}', name: 'File System', mimeType: 'text/plain', description: 'Access files by path', }, ``` ```javascript // Template resource if (uri.startsWith('template://')) { const name = uri.replace('template://', ''); const templatePath = path.join(CONFIG.templatesDir, `${name}.json`); if (fs.existsSync(templatePath)) { return { contents: [ { uri, mimeType: 'application/json', text: fs.readFileSync(templatePath, 'utf8'), }, ], }; } throw new Error(`Template not found: ${name}`); } // File resource if (uri.startsWith('file://')) { const filePath = uri.replace('file://', ''); if (fs.existsSync(filePath)) { const content = fs.readFileSync(filePath, 'utf8'); return { contents: [ { uri, mimeType: 'text/plain', text: content, }, ], }; } ``` ### Technical Analysis The `file://` MCP resource accepts a caller-controlled path and passes it directly to `fs.existsSync` and `fs.readFileSync`. The implementation does not: - Restrict access to an approved workspace or resource directory. - Canonicalize the path before applying access-control checks. - Reject absolute paths or `../` traversal sequences. - Deny access to sensitive files. - Enforce file-type or file-size restrictions. - Request user confirmation before accessing a new location. Consequently, the MCP server acts as an arbitrary local file-reading primitive under the privileges of the account running the server. The `template://` handler has a related directory-traversal weakness. The template name is i ...[truncated 1899 chars]
- Remediation
- ## Remediation Suggestions 1. **Define explicit resource roots:** Configure one or more approved workspace directories and prohibit access outside them. 2. **Canonicalize before authorization:** Resolve both the approved root and requested path with `fs.realpathSync` or an equivalent canonicalization operation. 3. **Enforce containment:** Verify that the canonical requested path equals the approved root or begins with the canonical root followed by the platform path separator. 4. **Reject unsafe inputs:** Reject absolute paths, null bytes, traversal components, malformed URI encoding, and unsupported URI forms. 5. **Validate template names:** Permit template identifiers matching a narrow pattern such as `^[A-Za-z0-9_-]+$`; do not accept path separators or traversal components. 6. **Restrict readable content:** Apply allowlists for extensions, maximum file sizes, and approved MIME types. Explicitly deny credential stores, SSH directories, environment files, and agent state. 7. **Apply least privilege:** Run the server under a dedicated account with access only to required workflow resources. 8. **Require authorization or confirmation:** Obtain explicit user approval before reading paths not previously authorized. 9. **Avoid leaking path details:** Return structured generic errors rather than exposing sensitive filesystem paths. 10. **Add security tests:** Test absolute paths, `../` traversal, encoded traversal, symlink escapes, Windows path forms, and attempts to read known sensitive locations. 11. **Remove unrestricted access if unnecessary:** If arbitrary files are not essential to the workflow, remove the `file://{path}` resource template entirely and expose only named, pre-registered resources.
