T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/mcp-server.js:117- Finding
Unrestricted Local File Disclosure Through MCP Resource Handlers
- Content
View full analysis
Vulnerability Details
File Location:
scripts/mcp-server.js, lines 117–121, 166–190
Vulnerability Type: Arbitrary local file read and directory traversal
Risk Level: HighVulnerable 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 tofs.existsSyncandfs.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
View remediation
Remediation Suggestions
- Define explicit resource roots: Configure one or more approved workspace directories and prohibit access outside them.
- Canonicalize before authorization: Resolve both the approved root and requested path with
fs.realpathSyncor an equivalent canonicalization operation. - Enforce containment: Verify that the canonical requested path equals the approved root or begins with the canonical root followed by the platform path separator.
- Reject unsafe inputs: Reject absolute paths, null bytes, traversal components, malformed URI encoding, and unsupported URI forms.
- Validate template names: Permit template identifiers matching a narrow pattern such as
^[A-Za-z0-9_-]+$; do not accept path separators or traversal components. - 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.
- Apply least privilege: Run the server under a dedicated account with access only to required workflow resources.
- Require authorization or confirmation: Obtain explicit user approval before reading paths not previously authorized.
- Avoid leaking path details: Return structured generic errors rather than exposing sensitive filesystem paths.
- Add security tests: Test absolute paths,
../traversal, encoded traversal, symlink escapes, Windows path forms, and attempts to read known sensitive locations. - 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.
