GHSA-q87f-qc2r-2gw4: SSRF
Ref: https://github.com/ihor-sokoliuk/mcp-searxng/issues/87#issuecomment-4645453694
Summary The weburlread tool fetches a caller-supplied URL server-side and converts it to markdown. An SSRF guard (assertUrlAllowed, which blocks private/loopback/metadata addresses) exists but runs only when MCPHTTPHARDEN=true, which is off by default. So in the default configuration there is no internal-address filtering, and an attacker who can influence the URL can make the server fetch internal services and cloud metadata and return their content. Confirmed on 1.1.0 (default config): weburlread fetched a local internal sentinel and returned its content.
Details dist/index.js (around lines 90-101): weburlread calls fetchAndConvertToMarkdown on the caller URL. dist/url-reader.js (around lines 44-52): assertUrlAllowed performs the private-IP/loopback check, but only when the hardening flag is set; dist/http-security.js (around line 11) defaults MCPHTTPHARDEN to off. With the default config the check is skipped entirely. Even when enabled, the check is literal-hostname based with no DNS-rebinding or redirect re-check (the fetch follows redirects). file:// is rejected, so this is HTTP/HTTPS SSRF.
PoC Re-validated on mcp-searxng 1.1.0 over MCP stdio in the default configuration (MCPHTTPHARDEN not set): tools: searxngwebsearch, weburlread weburlread({ url: "http://127.0.0.1:<port>/internal" }) -> server fetched the internal sentinel; SSRF: CONFIRMED The server fetched the loopback sentinel and returned its content. With MCPHTTPHARDEN=true the same request is blocked (policy error), confirming the guard exists but ships off. The same reaches http://169.254.169.254/... on cloud hosts.
Impact In the default configuration an attacker who can influence the URL (LLM-produced and steerable via prompt injection) can make the server fetch internal-only HTTP services and the cloud metadata endpoint, returning their contents into the model context for exfiltration. The protection that would prevent it is not enabled by default.
Remediation Enable the internal-address filtering by default (fail safe): make assertUrlAllowed run unconditionally and require an explicit opt-out only for trusted environments. Strengthen the check to resolve the host and reject loopback, link-local/metadata (169.254.0.0/16), 0.0.0.0/8, and private ranges, and re-validate on every redirect hop (or pin to the validated IP).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/mcp-searxngto a version that resolves this vulnerability.Fixed in 1.2.1 - Configuration
Change the default for MCP_HTTP_HARDEN from off to on so that assertUrlAllowed runs unconditionally (fail-safe). This ensures internal-address filtering (private/loopback/link-local/metadata) is applied for web_url_read in the default configuration.
mcp-searxng HTTP security (assertUrlAllowed / MCP_HTTP_HARDEN) MCP_HTTP_HARDEN = true (enable by default) - Configuration
Strengthen assertUrlAllowed to (1) resolve the hostname to an IP and reject loopback, link-local/metadata (169.254.0.0/16), 0.0.0.0/8, and private ranges, and (2) re-validate the URL policy on every redirect hop (or pin to the validated IP) because fetch follows redirects.
mcp-searxng SSRF guard (assertUrlAllowed in dist/url-reader.js) URL validation logic (host resolution + redirect re-check) = Resolve host to IP and validate each redirect hop
Event History
Frequently Asked Questions
Which deployments are exposed by default?
Deployments using the default configuration are exposed because MCP_HTTP_HARDEN defaults to off, so web_url_read does not apply private, loopback, or cloud-metadata address filtering. The issue was confirmed on version 1.1.0 with the default configuration.
What does an attacker need to exploit this?
An attacker needs to be able to influence a URL processed by the web_url_read tool. The server then performs the request, potentially allowing the attacker to retrieve content from internal services or cloud metadata endpoints.
How can I determine whether my instance has the basic SSRF guard enabled?
Check whether MCP_HTTP_HARDEN is explicitly set to true. If it is unset or false, the guard is skipped entirely for web_url_read requests.
Is enabling MCP_HTTP_HARDEN a complete mitigation if patching is delayed?
No. It enables literal-hostname checks for private, loopback, and metadata addresses, but the provided information states that DNS rebinding and redirect targets are not re-checked, while the fetch follows redirects. It is still a meaningful improvement over the default disabled state.