A Server-Side Request Forgery (SSRF) vulnerability was discovered in the webpage-to-markdown conversion feature of the markdownify-mcp server. This vulnerability allows an attacker to bypass private IP restrictions through hostname-based bypass and HTTP redirect chains, enabling access to internal network services. The impact includes potential exposure of sensitive internal administrative endpoints and credentials.
The markdownify-mcp server provides functionality to convert web pages to markdown format by fetching user-supplied URLs. It performs an HTTP request from the server to the provided URL and converts the response (HTML) to markdown format.
The issue arises because the feature performs these HTTP requests without properly validating the user-supplied URL. In particular, two critical flaws exist:
is_ip_private() function only validates IP address strings but does not resolve hostnames to their actual IP addressesfetch() function automatically follows HTTP redirects without re-validating the redirected destination URLsThis allows attackers to access internal services through hostname bypass (e.g., using "localhost" instead of "127.0.0.1") or by chaining HTTP redirections from public or localhost URLs to any internal addresses (127.0.0.1, 192.168.x.x, 10.x.x.x, 172.16-31.x.x).
The fetch() function is called without proper URL validation or hostname resolution, and redirects are automatically followed without re-validation, which enables attackers to access internal services on the private network.
src/server.ts Lines 41-42
const { name, arguments: args } = request.params;
const validatedArgs = RequestPayloadSchema.parse(args);
src/server.ts Lines 55-62
const parsedUrl = new URL(validatedArgs.url);
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
throw new Error("Only http: and https: schemes are allowed.");
}
if (is_ip_private(parsedUrl.hostname)) {
throw new Error(`Fetching ${validatedArgs.url} is potentially dangerous, aborting.`);
}
The validation only checks the hostname string without DNS resolution: