{"id":"CVE-2026-54688","aliases":["EUVD-2026-78923","GHSA-q87f-qc2r-2gw4"],"status":"published","title":"mcp-searxng: SSRF in web_url_read: the internal-address guard is disabled by default (MCP_HTTP_HARDEN off)","description":"mcp-searxng is a Model Context Protocol server that gives AI assistants web search and URL-reading capabilities through SearXNG. Prior to 1.2.0, web_url_read passes a caller-supplied URL to the server-side fetch path while assertUrlAllowed() in src/url-reader.ts runs only when MCP_HTTP_HARDEN is enabled, even though MCP_HTTP_HARDEN is disabled by default in src/http-security.ts. In the default configuration, an attacker who influences the URL selected by a user or AI agent can make the server fetch loopback, private-network, or cloud metadata endpoint resources and return their contents into the model context. file:// URLs remain rejected, and the separate DNS-resolution and redirect-validation bypasses are outside this record. This issue is fixed in version 1.2.0.","severity":{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00499,"percentile":0.43121,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-918"],"published":"2026-08-19T19:23:08Z","modified":"2026-10-28T02:31:11Z","fixes":[{"ecosystem":"npm","package":"mcp-searxng","fixed_in":["1.2.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"mcp-searxng","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.2.1"}]}]},{"source":"osv","ecosystem":"npm","package":"mcp-searxng","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.2.1"}]}]}],"products":[{"vendor":"ihor-sokoliuk","product":"mcp-searxng"}],"references":[{"url":"https://github.com/ihor-sokoliuk/mcp-searxng/security/advisories/GHSA-q87f-qc2r-2gw4","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/ihor-sokoliuk/mcp-searxng/issues/87#issuecomment-4645453694","tags":["x_refsource_MISC","report","web"]},{"url":"https://github.com/ihor-sokoliuk/mcp-searxng/commit/48e5ecdcb4166a60b94c252dbe74b0a318110ac4","tags":["x_refsource_MISC","fix"]},{"url":"https://github.com/ihor-sokoliuk/mcp-searxng/releases/tag/v1.2.0","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/ihor-sokoliuk/mcp-searxng/releases/tag/v1.2.1","tags":["web"]},{"url":"https://github.com/advisories/GHSA-q87f-qc2r-2gw4"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/54xxx/CVE-2026-54688.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54688","tags":["advisory"]},{"url":"https://github.com/ihor-sokoliuk/mcp-searxng","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-54688","title":"mcp-searxng: SSRF in web_url_read: the internal-address guard is disabled by default (MCP_HTTP_HARDEN off)","description":"mcp-searxng is a Model Context Protocol server that gives AI assistants web search and URL-reading capabilities through SearXNG. Prior to 1.2.0, web_url_read passes a caller-supplied URL to the server-side fetch path while assertUrlAllowed() in src/url-reader.ts runs only when MCP_HTTP_HARDEN is enabled, even though MCP_HTTP_HARDEN is disabled by default in src/http-security.ts. In the default configuration, an attacker who influences the URL selected by a user or AI agent can make the server fetch loopback, private-network, or cloud metadata endpoint resources and return their contents into the model context. file:// URLs remain rejected, and the separate DNS-resolution and redirect-validation bypasses are outside this record. This issue is fixed in version 1.2.0.","status":"published","published":"2026-09-15T17:46:23.073Z","modified":"2026-09-15T19:01:31.029Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T13:37:58.613221Z"}],"euvd":[{"id":"EUVD-2026-78923","description":"mcp-searxng is a Model Context Protocol server that gives AI assistants web search and URL-reading capabilities through SearXNG. Prior to 1.2.0, web_url_read passes a caller-supplied URL to the server-side fetch path while assertUrlAllowed() in src/url-reader.ts runs only when MCP_HTTP_HARDEN is enabled, even though MCP_HTTP_HARDEN is disabled by default in src/http-security.ts. In the default configuration, an attacker who influences the URL selected by a user or AI agent can make the server fetch loopback, private-network, or cloud metadata endpoint resources and return their contents into the model context. file:// URLs remain rejected, and the separate DNS-resolution and redirect-validation bypasses are outside this record. This issue is fixed in version 1.2.0.","status":"published","published":"2026-09-15T17:46:23Z","modified":"2026-09-15T19:01:31Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T17:28:17.333425Z"}],"ghsa":[{"id":"GHSA-q87f-qc2r-2gw4","title":"SearXNG MCP Server is Vulnerable to SSRF in web_url_read: the internal-address guard is disabled by default (MCP_HTTP_HARDEN off)","description":"Ref: https://github.com/ihor-sokoliuk/mcp-searxng/issues/87#issuecomment-4645453694\n\n\n### Summary\nThe web_url_read 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 MCP_HTTP_HARDEN=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): web_url_read fetched a local internal sentinel and returned its content.\n\n### Details\ndist/index.js (around lines 90-101): web_url_read 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 MCP_HTTP_HARDEN 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.\n\n### PoC\nRe-validated on mcp-searxng 1.1.0 over MCP stdio in the default configuration (MCP_HTTP_HARDEN not set):\n```\ntools: searxng_web_search, web_url_read\nweb_url_read({ url: \"http://127.0.0.1:\u003cport\u003e/internal\" }) -\u003e server fetched the internal sentinel; SSRF: CONFIRMED\n```\nThe server fetched the loopback sentinel and returned its content. With MCP_HTTP_HARDEN=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.\n\n### Impact\nIn 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.\n\n### Remediation\nEnable 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).","status":"published","published":"2026-08-19T19:23:08Z","modified":"2026-08-19T19:23:12Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:41:03.602876Z"}],"nvd":[{"id":"CVE-2026-54688","description":"mcp-searxng is a Model Context Protocol server that gives AI assistants web search and URL-reading capabilities through SearXNG. Prior to 1.2.0, web_url_read passes a caller-supplied URL to the server-side fetch path while assertUrlAllowed() in src/url-reader.ts runs only when MCP_HTTP_HARDEN is enabled, even though MCP_HTTP_HARDEN is disabled by default in src/http-security.ts. In the default configuration, an attacker who influences the URL selected by a user or AI agent can make the server fetch loopback, private-network, or cloud metadata endpoint resources and return their contents into the model context. file:// URLs remain rejected, and the separate DNS-resolution and redirect-validation bypasses are outside this record. This issue is fixed in version 1.2.0.","status":"published","published":"2026-09-15T18:17:23.333Z","modified":"2026-09-30T17:51:56.193Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:12:47.668237Z"}],"osv":[{"id":"CVE-2026-54688","title":"mcp-searxng: SSRF in web_url_read: the internal-address guard is disabled by default (MCP_HTTP_HARDEN off)","description":"mcp-searxng is a Model Context Protocol server that gives AI assistants web search and URL-reading capabilities through SearXNG. Prior to 1.2.0, web_url_read passes a caller-supplied URL to the server-side fetch path while assertUrlAllowed() in src/url-reader.ts runs only when MCP_HTTP_HARDEN is enabled, even though MCP_HTTP_HARDEN is disabled by default in src/http-security.ts. In the default configuration, an attacker who influences the URL selected by a user or AI agent can make the server fetch loopback, private-network, or cloud metadata endpoint resources and return their contents into the model context. file:// URLs remain rejected, and the separate DNS-resolution and redirect-validation bypasses are outside this record. This issue is fixed in version 1.2.0.","status":"published","published":"2026-09-15T17:46:23.073Z","modified":"2026-10-28T02:31:11.780844345Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:45:10.818486Z"},{"id":"GHSA-q87f-qc2r-2gw4","title":"SearXNG MCP Server is Vulnerable to SSRF in web_url_read: the internal-address guard is disabled by default (MCP_HTTP_HARDEN off)","description":"Ref: https://github.com/ihor-sokoliuk/mcp-searxng/issues/87#issuecomment-4645453694\n\n\n### Summary\nThe web_url_read 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 MCP_HTTP_HARDEN=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): web_url_read fetched a local internal sentinel and returned its content.\n\n### Details\ndist/index.js (around lines 90-101): web_url_read 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 MCP_HTTP_HARDEN 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.\n\n### PoC\nRe-validated on mcp-searxng 1.1.0 over MCP stdio in the default configuration (MCP_HTTP_HARDEN not set):\n```\ntools: searxng_web_search, web_url_read\nweb_url_read({ url: \"http://127.0.0.1:\u003cport\u003e/internal\" }) -\u003e server fetched the internal sentinel; SSRF: CONFIRMED\n```\nThe server fetched the loopback sentinel and returned its content. With MCP_HTTP_HARDEN=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.\n\n### Impact\nIn 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.\n\n### Remediation\nEnable 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).","status":"published","published":"2026-08-19T19:23:08Z","modified":"2026-08-19T19:33:55.245527Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:46:54.40888Z"}]}}
