{"answers":{"affected":"2 open source packages ship an affected version, including mcp-searxng.","exploited":"There is no known exploitation of GHSA-hjwh-xvfw-qrwj in the wild and no public exploit code.","fix":"Upgrade mcp-searxng to 1.12.0 or later.","what":"GHSA-hjwh-xvfw-qrwj is a vulnerability in mcp-searxng, published on 19 Aug 2026. It can only be exploited from the same machine or local network, with no action from the victim."},"fix_prompt":"Check this codebase for GHSA-hjwh-xvfw-qrwj and fix it if it is affected.\n\nWhat it is: GHSA-hjwh-xvfw-qrwj is a vulnerability in mcp-searxng, published on 19 Aug 2026. It can only be exploited from the same machine or local network, with no action from the victim.\nExploitation: There is no known exploitation of GHSA-hjwh-xvfw-qrwj in the wild and no public exploit code.\n\nAffected packages and fixed versions:\n- mcp-searxng (npm): affected all versions; fixed in 1.12.0\n- mcp-searxng (npm): affected all versions; fixed in 1.12.0\n\nTask:\n1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.\n2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.\n3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.\n4. Run the tests and summarise what changed and why.\n5. If nothing in the project is affected, say so and change nothing.\n\nReference: https://insights.sbomify.com/GHSA-hjwh-xvfw-qrwj/ (Markdown: https://insights.sbomify.com/GHSA-hjwh-xvfw-qrwj/index.md)","id":"GHSA-hjwh-xvfw-qrwj","markdown":"https://insights.sbomify.com/GHSA-hjwh-xvfw-qrwj/index.md","name":"GHSA-hjwh-xvfw-qrwj","record":{"aliases":[],"analysis":{"component_type":"library","fix_type":"patch","impacts":["data_read","security_bypass"],"network_reachable":"adjacent_or_local","non_default_config":false,"product_category":"MCP SearXNG library","requires_auth":"none","summary":"An attacker with log access or MCP client connectivity can recover SearXNG Basic Authentication credentials exposed in logs and error responses.","user_interaction":"not_required","vuln_class":"information_disclosure"},"analysis_generated_by":"qwen3.8-flash-next","assigner":null,"cpe":[],"cvss":{"score":null,"severity":null,"source":null,"vector":null,"version":null},"cwes":[],"description":"### Summary\n\nmcp-searxng version 1.11.0 exposes SearXNG Basic Authentication credentials embedded in the `SEARXNG_URL` environment variable.\n\nWhen the server starts in STDIO mode and an MCP client connects, the complete `SEARXNG_URL`, including its username and password, is sent to the client through an MCP `notifications/message` logging notification.\n\nAdditionally, when URL validation fails, the complete credential-bearing URL is included in the configuration error. This error is logged through MCP and returned to the client as a JSON-RPC error response.\n\nFor example, a value such as:\n\n```text\nhttp://username:password@searxng.example.com\n```\n\nis exposed without redaction.\n\nA connected MCP client or anyone with access to captured server logs may recover the SearXNG credentials and use them to access the configured SearXNG instance.\n\nThe issue was confirmed in:\n\n```text\nmcp-searxng 1.11.0\n```\n\nSuggested severity: **Medium**\n\n### Details\n\nmcp-searxng supports SearXNG Basic Authentication by embedding credentials in the URL userinfo component:\n\n```text\nhttps://username:password@searxng.example.com\n```\n\nThe project contains a redaction function named `redactSearxngInstanceUrl()`, but it is not used in several logging and error-handling paths.\n\n#### Startup console disclosure\n\nIn `src/index.ts:373-378`, the server retrieves the raw SearXNG URLs and writes them directly to stderr:\n\n```typescript\nconst searxngInstances = getSearxngInstances();\n\nif (searxngInstances.length \u003e 0) {\n  console.error(`🌐 SearXNG URLs: ${searxngInstances.join(\"; \")}`);\n}\n```\n\n`getSearxngInstances()` returns the unmodified environment-variable values.\n\nRelevant code in `src/searxng-instances.ts:25-38`:\n\n```typescript\nexport function parseSearxngUrls(\n  raw: string | undefined = process.env.SEARXNG_URL\n): string[] {\n  if (raw === undefined) {\n    return [];\n  }\n\n  return raw\n    .split(\";\")\n    .map((entry) =\u003e entry.trim())\n    .filter((entry) =\u003e entry !== \"\");\n}\n\nexport function getSearxngInstances(): string[] {\n  return parseSearxngUrls();\n}\n```\n\n#### MCP logging notification disclosure\n\nAfter the MCP client connects, `src/index.ts:388-393` sends the complete URL through the MCP logging interface:\n\n```typescript\nconst searxngInstances = getSearxngInstances();\n\nlogMessage(\n  mcpServer,\n  \"info\",\n  `SearXNG URLs: ${\n    searxngInstances.length \u003e 0\n      ? searxngInstances.join(\"; \")\n      : \"not configured\"\n  }`\n);\n```\n\n`logMessage()` passes this value to `sendLoggingMessage()` in `src/logging.ts:15-25`:\n\n```typescript\nmcpServer.sendLoggingMessage({\n  level,\n  data: notificationData\n});\n```\n\nAs a result, the connected MCP client receives a message containing the username and password:\n\n```json\n{\n  \"method\": \"notifications/message\",\n  \"params\": {\n    \"level\": \"info\",\n    \"data\": {\n      \"message\": \"SearXNG URLs: http://username:password@searxng.example.com\"\n    }\n  },\n  \"jsonrpc\": \"2.0\"\n}\n```\n\n#### Configuration error disclosure\n\nThe URL validation function includes the complete unredacted value in error messages.\n\nRelevant code in `src/searxng-instances.ts:44-52`:\n\n```typescript\nexport function validateSearxngInstanceUrl(\n  value: string\n): string | null {\n  try {\n    const url = new URL(value);\n\n    if (![\"http:\", \"https:\"].includes(url.protocol)) {\n      return `SEARXNG_URL invalid protocol for \"${value}\": ${url.protocol}`;\n    }\n  } catch {\n    return `SEARXNG_URL invalid format: ${value}`;\n  }\n\n  return null;\n}\n```\n\nThe validation error is aggregated by `validateEnvironment()` in `src/error-handler.ts:175-203`:\n\n```typescript\nconst validationError =\n  validateSearxngInstanceUrl(searxngUrl);\n\nif (validationError) {\n  issues.push(validationError);\n}\n```\n\nThe complete error is then thrown from `src/search.ts:689-693`:\n\n```typescript\nconst validationError = validateEnvironment();\n\nif (validationError) {\n  logMessage(mcpServer, \"error\", \"Configuration invalid\");\n  throw new MCPSearXNGError(validationError);\n}\n```\n\nThe tool handler in `src/index.ts:254-260` sends the error message and stack trace through MCP logging, then rethrows it:\n\n```typescript\nlogMessage(\n  mcpServer,\n  \"error\",\n  `Tool execution error: ${\n    error instanceof Error\n      ? error.message\n      : String(error)\n  }`,\n  {\n    tool: name,\n    args: args,\n    error:\n      error instanceof Error\n        ? error.stack\n        : String(error)\n  }\n);\n\nthrow error;\n```\n\nRethrowing the error causes the same unredacted credential-bearing URL to be returned in the JSON-RPC error response.\n\n#### Existing redaction function is not used\n\nThe project already contains a suitable redaction function in `src/searxng-instances.ts:57-69`:\n\n```typescript\nexport function redactSearxngInstanceUrl(\n  raw: string\n): string {\n  try {\n    const url = new URL(raw);\n\n    if (!url.username \u0026\u0026 !url.password) {\n      return raw;\n    }\n\n    url.username = \"\";\n    url.password = \"\";\n    return url.toString();\n  } catch {\n    return raw.replace(\n      /^([a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/)[^/]*@/,\n      \"$1\"\n    );\n  }\n}\n```\n\nHowever, this function is not applied before startup logging, MCP logging, or configuration error construction.\n\nThe MCP manifest also marks `SEARXNG_URL` as non-secret in `.mcp/server.json:20-25`:\n\n```json\n{\n  \"name\": \"SEARXNG_URL\",\n  \"description\": \"URL of your SearXNG instance\",\n  \"isRequired\": true,\n  \"isSecret\": false,\n  \"format\": \"string\"\n}\n```\n\nBecause credentials may be embedded in this variable, it should be classified as a secret.\n\n### PoC\n\nThe following proof of concept uses fake credentials. A real SearXNG server is not required.\n\n#### Requirements\n\n```text\nNode.js 20 or newer\nnpm\nmcp-searxng 1.11.0 source code\n```\n\n#### Build the application\n\n```bash\nunzip mcp-searxng-main.zip\ncd mcp-searxng-main\n\nnpm ci\nnpm run build\n```\n\n#### Test 1: Credential disclosure through MCP logging\n\nCreate an MCP initialization request:\n\n```bash\ncat \u003e /tmp/mcp-init.jsonl \u003c\u003c'EOF'\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"credential-leak-poc\",\"version\":\"1.0.0\"}}}\nEOF\n```\n\nStart the server with fake credentials embedded in a valid HTTP URL:\n\n```bash\nSEARXNG_URL='http://MCP_POC_USER_7391:MCP_POC_PASS_7391@127.0.0.1:9' \\\ntimeout 8s node dist/cli.js \\\n\u003c /tmp/mcp-init.jsonl \\\n2\u003e\u00261 | tee credential-log-leak.txt\n```\n\nSearch the output for the credentials:\n\n```bash\ngrep -nE \\\n'MCP_POC_USER_7391|MCP_POC_PASS_7391' \\\ncredential-log-leak.txt\n```\n\n#### Observed result\n\nThe complete credential-bearing URL is exposed:\n\n```text\nSearXNG URLs: http://MCP_POC_USER_7391:MCP_POC_PASS_7391@127.0.0.1:9\n```\n\nIt is also delivered to the MCP client:\n\n```json\n{\n  \"method\": \"notifications/message\",\n  \"params\": {\n    \"level\": \"info\",\n    \"data\": {\n      \"message\": \"SearXNG URLs: http://MCP_POC_USER_7391:MCP_POC_PASS_7391@127.0.0.1:9\"\n    }\n  },\n  \"jsonrpc\": \"2.0\"\n}\n```\n\nThis confirms that a connected MCP client can recover the configured username and password without accessing the host environment.\n\n#### Test 2: Credential disclosure through JSON-RPC errors\n\nCreate initialization and tool-call requests:\n\n```bash\ncat \u003e /tmp/mcp-error-poc.jsonl \u003c\u003c'EOF'\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"credential-error-poc\",\"version\":\"1.0.0\"}}}\n{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"searxng_web_search\",\"arguments\":{\"query\":\"credential leak test\"}}}\nEOF\n```\n\nStart the server with a credential-bearing URL that uses an unsupported protocol:\n\n```bash\nSEARXNG_URL='ftp://MCP_POC_USER_7391:MCP_POC_PASS_7391@example.invalid' \\\ntimeout 8s node dist/cli.js \\\n\u003c /tmp/mcp-error-poc.jsonl \\\n2\u003e\u00261 | tee credential-error-leak.txt\n```\n\nSearch the response:\n\n```bash\ngrep -nE \\\n'MCP_POC_USER_7391|MCP_POC_PASS_7391' \\\ncredential-error-leak.txt\n```\n\n#### Observed result\n\nThe complete URL is exposed in the MCP logging notification:\n\n```text\nTool execution error: Configuration Issues: SEARXNG_URL invalid protocol","ecosystems":["npm"],"exploits":{"exploitdb":null,"first_seen":null,"github_poc":null,"max_poc_stars":null,"metasploit":null,"nuclei":null,"refs":[],"tier":null},"has_fix":true,"headline":"SearXNG Basic Authentication Credentials Exposed Through MCP Logs and JSON-RPC Error Responses","id":"GHSA-hjwh-xvfw-qrwj","indexable":true,"kev":null,"kind":"advisory","links":{"ecosystem":"npm","product":null,"products":[],"type":"information_disclosure","year":"2026"},"n_packages":2,"n_references":null,"packages":[{"ecosystem":"npm","fixed":["1.12.0"],"introduced":["0"],"last_affected":[],"package":"mcp-searxng","purl":null,"source":"GHSA-hjwh-xvfw-qrwj"},{"ecosystem":"npm","fixed":["1.12.0"],"introduced":["0"],"last_affected":[],"package":"mcp-searxng","purl":"pkg:npm/mcp-searxng","source":"GHSA-hjwh-xvfw-qrwj"}],"products":null,"published":"2026-08-19","related":[],"sources":[{"class":"attribution","licence":"CC BY 4.0","name":"GitHub Advisory Database","prefix":"GHSA"}],"ssvc":{"automatable":null,"exploitation":null,"technical_impact":null},"state":null,"updated":null,"vendors":null},"summary":"An attacker with log access or MCP client connectivity can recover SearXNG Basic Authentication credentials exposed in logs and error responses.","url":"https://insights.sbomify.com/GHSA-hjwh-xvfw-qrwj/"}