Summary
webpage-to-markdown URL fetching appears to still be affected by the SSRF class tracked as CVE-2025-65512 in the current repository version (package.json reports 1.1.0). In addition to hostname/DNS-based bypasses, the current validator also accepts bracketed IPv6 loopback URLs such as http://[::1]:<port>/....
The affected path is:
server.ts: URL tools (webpage-to-markdown, youtube-to-markdown, bing-search-to-markdown) pass user-controlled url values to Markdownify.toMarkdown.
Markdownify.ts: safeFetch() calls validateUrl(currentUrl) and then fetch(currentUrl, { redirect: "manual" }).
utils.ts: validateUrl() checks the scheme and then calls private-ip on parsed.hostname, but does not check the resolved destination IP.
Impact
An attacker who can invoke a URL-based MCP tool can cause the server process to fetch loopback, link-local, or otherwise internal HTTP resources if the hostname validation does not reflect the actual network destination. Depending on deployment, this may expose cloud metadata, internal service responses, local admin interfaces, or other network-local data readable by the server process.
This is most severe when the MCP server runs in a cloud/VPC/container environment or is reachable through a remote MCP gateway. In a strictly local, single-user setup, the practical attack surface is lower.
Local verification
I verified the issue locally against the project code without modifying source files:
- Started a temporary HTTP server bound only to
::1.
- Called the project's URL validation and fetch path with
http://[::1]:<port>/metadata.
- The validator accepted the URL and the fetch returned the loopback-only response.
Observed result:
{
"address": "::1",
"url": "http://[::1]:38069/metadata",
"validateUrlAccepted": true,
"responseStatus": 200,
"responseText": "LOCAL_METADATA_TOKEN"
}
The issue is that security-relevant destination context, especially the resolved IP address, is not part of the authorization decision. Redirect targets are revalidated before following, which is good, but each target still has the same unresolved-IP weakness.
Expected behavior
URL fetching should reject loopback, link-local, private, and reserved destinations based on the actual resolved address, not only on the textual hostname. The same check should be applied to every redirect target.
Related public record
This appears related to CVE-2025-65512. The reason for filing is that the current repository version appears to remain affected and the bracketed IPv6 loopback form is a concrete bypass variant.
Summary
webpage-to-markdownURL fetching appears to still be affected by the SSRF class tracked as CVE-2025-65512 in the current repository version (package.jsonreports1.1.0). In addition to hostname/DNS-based bypasses, the current validator also accepts bracketed IPv6 loopback URLs such ashttp://[::1]:<port>/....The affected path is:
server.ts: URL tools (webpage-to-markdown,youtube-to-markdown,bing-search-to-markdown) pass user-controlledurlvalues toMarkdownify.toMarkdown.Markdownify.ts:safeFetch()callsvalidateUrl(currentUrl)and thenfetch(currentUrl, { redirect: "manual" }).utils.ts:validateUrl()checks the scheme and then callsprivate-iponparsed.hostname, but does not check the resolved destination IP.Impact
An attacker who can invoke a URL-based MCP tool can cause the server process to fetch loopback, link-local, or otherwise internal HTTP resources if the hostname validation does not reflect the actual network destination. Depending on deployment, this may expose cloud metadata, internal service responses, local admin interfaces, or other network-local data readable by the server process.
This is most severe when the MCP server runs in a cloud/VPC/container environment or is reachable through a remote MCP gateway. In a strictly local, single-user setup, the practical attack surface is lower.
Local verification
I verified the issue locally against the project code without modifying source files:
::1.http://[::1]:<port>/metadata.Observed result:
{ "address": "::1", "url": "http://[::1]:38069/metadata", "validateUrlAccepted": true, "responseStatus": 200, "responseText": "LOCAL_METADATA_TOKEN" }The issue is that security-relevant destination context, especially the resolved IP address, is not part of the authorization decision. Redirect targets are revalidated before following, which is good, but each target still has the same unresolved-IP weakness.
Expected behavior
URL fetching should reject loopback, link-local, private, and reserved destinations based on the actual resolved address, not only on the textual hostname. The same check should be applied to every redirect target.
Related public record
This appears related to CVE-2025-65512. The reason for filing is that the current repository version appears to remain affected and the bracketed IPv6 loopback form is a concrete bypass variant.