| Titolo | zcaceres markdownify-mcp / mcp-markdownify-server up to 1.1.0 CWE-59: Improper Link Resolution Before File Access ('Link Follo |
|---|
| Descrizione | A vulnerability was found in zcaceres markdownify-mcp, also distributed as
mcp-markdownify-server, up to version 1.1.0. The issue affects the local file
access boundary enforced by MD_ALLOWED_PATHS and MD_SHARE_DIR.
The vulnerable component is the path authorization helper in src/utils.ts.
The function assertPathAllowed() resolves and normalizes the user supplied file
path and then checks it with isWithinDirectory(). The latter compares normalized
path strings with startsWith(). This authorization decision does not canonicalize
the requested path or allowed root with realpath before access.
The file access sinks later dereference the original path. In particular,
Markdownify.get() in src/Markdownify.ts calls assertPathAllowed() and then reads
the requested path with fs.promises.readFile(). Node.js follows symbolic links
during this read. Therefore, a path that appears to be inside an allowed
directory can be a symbolic link to a target outside the allowed directory. The
authorization check accepts the allowed-looking path, while the actual file read
returns content from the symlink target.
Authentication required: yes, in the sense that the attacker must be able to
invoke the MCP file tool or otherwise control a file-input request. User
interaction required: no, assuming the attacker already has access to the MCP
tool interface and can influence a path inside an allowed directory.
Technical Details
- Affected file/function: src/utils.ts assertPathAllowed(), src/utils.ts isWithinDirectory(), src/Markdownify.ts Markdownify.get(), src/Markdownify.ts Markdownify.toMarkdown()
- Vulnerable parameter: filepath
- Security boundary: MD_ALLOWED_PATHS / MD_SHARE_DIR
- Attack vector: Local by default because the server uses stdio transport; may become Network if deployed behind a remote MCP gateway or exposed service
- Privileges required: Low
- Trigger condition: the attacker can invoke a file-input MCP tool and can place or influence a symlink under an allowed directory
Impact
- Confidentiality: High
- Integrity: None
- Availability: None
The issue can disclose files outside the configured allowed directory that are
readable by the server process. Examples include application configuration,
environment files, internal documents, source files, and container-mounted
tokens, depending on deployment. The vulnerability does not bypass operating
system file permissions.
CVSS v3.1
Score: 5.5 (Medium) for the default local stdio deployment
Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Environmental severity can be higher. If the MCP server is exposed to remote
users or the allowed directory is a user-writable upload/share/CI directory, the
practical severity may be High or Critical.
Timeline
- Discovered: 2026-06-03
- Vendor notified: 2026-06-03
- Patch released: [unknown]
- Public disclosure: 2026-06-03
Countermeasure
Canonicalize both the requested path and each allowed root before authorization,
for example with fs.realpath or fs.promises.realpath. Compare the canonical
paths using path-boundary-aware logic such as path.relative() with separator
handling instead of startsWith(). Consider rejecting symbolic links outright or
allowing them only when their canonical target remains inside an allowed root.
Also address time-of-check/time-of-use risk where the file is checked and then
opened later. |
|---|
| Fonte | ⚠️ https://github.com/zcaceres/markdownify-mcp/issues/108 |
|---|
| Utente | Dem000000 (UID 98564) |
|---|
| Sottomissione | 03/06/2026 15:24 (1 mese fa) |
|---|
| Moderazione | 04/07/2026 07:22 (1 month later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 376295 [zcaceres markdownify-mcp fino a 1.1.0 src/Markdownify.ts assertPathAllowed escalationi di privilegi] |
|---|
| Punti | 20 |
|---|