PT-2026-83510 · Npm · Mcp-Searxng
Published
2026-08-19
·
Updated
2026-08-19
CVSS v3.1
5.5
Medium
| Vector | AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
Summary
mcp-searxng version 1.11.0 exposes SearXNG Basic Authentication credentials embedded in the
SEARXNG URL environment variable.When 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.Additionally, 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.
For example, a value such as:
text
http://username:password@searxng.example.comis exposed without redaction.
A 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.
The issue was confirmed in:
text
mcp-searxng 1.11.0Suggested severity: Medium
Details
mcp-searxng supports SearXNG Basic Authentication by embedding credentials in the URL userinfo component:
text
https://username:password@searxng.example.comThe project contains a redaction function named
redactSearxngInstanceUrl(), but it is not used in several logging and error-handling paths.Startup console disclosure
In
src/index.ts:373-378, the server retrieves the raw SearXNG URLs and writes them directly to stderr:typescript
const searxngInstances = getSearxngInstances();
if (searxngInstances.length > 0) {
console.error(`🌐 SearXNG URLs: ${searxngInstances.join("; ")}`);
}getSearxngInstances() returns the unmodified environment-variable values.Relevant code in
src/searxng-instances.ts:25-38:typescript
export function parseSearxngUrls(
raw: string | undefined = process.env.SEARXNG URL
): string[] {
if (raw === undefined) {
return [];
}
return raw
.split(";")
.map((entry) => entry.trim())
.filter((entry) => entry !== "");
}
export function getSearxngInstances(): string[] {
return parseSearxngUrls();
}MCP logging notification disclosure
After the MCP client connects,
src/index.ts:388-393 sends the complete URL through the MCP logging interface:typescript
const searxngInstances = getSearxngInstances();
logMessage(
mcpServer,
"info",
`SearXNG URLs: ${
searxngInstances.length > 0
? searxngInstances.join("; ")
: "not configured"
}`
);logMessage() passes this value to sendLoggingMessage() in src/logging.ts:15-25:typescript
mcpServer.sendLoggingMessage({
level,
data: notificationData
});As a result, the connected MCP client receives a message containing the username and password:
json
{
"method": "notifications/message",
"params": {
"level": "info",
"data": {
"message": "SearXNG URLs: http://username:password@searxng.example.com"
}
},
"jsonrpc": "2.0"
}Configuration error disclosure
The URL validation function includes the complete unredacted value in error messages.
Relevant code in
src/searxng-instances.ts:44-52:typescript
export function validateSearxngInstanceUrl(
value: string
): string | null {
try {
const url = new URL(value);
if (!["http:", "https:"].includes(url.protocol)) {
return `SEARXNG URL invalid protocol for "${value}": ${url.protocol}`;
}
} catch {
return `SEARXNG URL invalid format: ${value}`;
}
return null;
}The validation error is aggregated by
validateEnvironment() in src/error-handler.ts:175-203:typescript
const validationError =
validateSearxngInstanceUrl(searxngUrl);
if (validationError) {
issues.push(validationError);
}The complete error is then thrown from
src/search.ts:689-693:typescript
const validationError = validateEnvironment();
if (validationError) {
logMessage(mcpServer, "error", "Configuration invalid");
throw new MCPSearXNGError(validationError);
}The tool handler in
src/index.ts:254-260 sends the error message and stack trace through MCP logging, then rethrows it:typescript
logMessage(
mcpServer,
"error",
`Tool execution error: ${
error instanceof Error
? error.message
: String(error)
}`,
{
tool: name,
args: args,
error:
error instanceof Error
? error.stack
: String(error)
}
);
throw error;Rethrowing the error causes the same unredacted credential-bearing URL to be returned in the JSON-RPC error response.
Existing redaction function is not used
The project already contains a suitable redaction function in
src/searxng-instances.ts:57-69:typescript
export function redactSearxngInstanceUrl(
raw: string
): string {
try {
const url = new URL(raw);
if (!url.username && !url.password) {
return raw;
}
url.username = "";
url.password = "";
return url.toString();
} catch {
return raw.replace(
/^([a-zA-Z][a-zA-Z0-9+.-]*://)[^/]*@/,
"$1"
);
}
}However, this function is not applied before startup logging, MCP logging, or configuration error construction.
The MCP manifest also marks
SEARXNG URL as non-secret in .mcp/server.json:20-25:json
{
"name": "SEARXNG URL",
"description": "URL of your SearXNG instance",
"isRequired": true,
"isSecret": false,
"format": "string"
}Because credentials may be embedded in this variable, it should be classified as a secret.
PoC
The following proof of concept uses fake credentials. A real SearXNG server is not required.
Requirements
text
Node.js 20 or newer
npm
mcp-searxng 1.11.0 source codeBuild the application
bash
unzip mcp-searxng-main.zip
cd mcp-searxng-main
npm ci
npm run buildTest 1: Credential disclosure through MCP logging
Create an MCP initialization request:
bash
cat > /tmp/mcp-init.jsonl <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"credential-leak-poc","version":"1.0.0"}}}
EOFStart the server with fake credentials embedded in a valid HTTP URL:
bash
SEARXNG URL='http://MCP POC USER 7391:MCP POC PASS 7391@127.0.0.1:9'
timeout 8s node dist/cli.js
< /tmp/mcp-init.jsonl
2>&1 | tee credential-log-leak.txtSearch the output for the credentials:
bash
grep -nE
'MCP POC USER 7391|MCP POC PASS 7391'
credential-log-leak.txtObserved result
The complete credential-bearing URL is exposed:
text
SearXNG URLs: http://MCP POC USER 7391:MCP POC PASS 7391@127.0.0.1:9It is also delivered to the MCP client:
json
{
"method": "notifications/message",
"params": {
"level": "info",
"data": {
"message": "SearXNG URLs: http://MCP POC USER 7391:MCP POC PASS 7391@127.0.0.1:9"
}
},
"jsonrpc": "2.0"
}This confirms that a connected MCP client can recover the configured username and password without accessing the host environment.
Test 2: Credential disclosure through JSON-RPC errors
Create initialization and tool-call requests:
bash
cat > /tmp/mcp-error-poc.jsonl <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"credential-error-poc","version":"1.0.0"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"searxng web search","arguments":{"query":"credential leak test"}}}
EOFStart the server with a credential-bearing URL that uses an unsupported protocol:
bash
SEARXNG URL='ftp://MCP POC USER 7391:MCP POC PASS 7391@example.invalid'
timeout 8s node dist/cli.js
< /tmp/mcp-error-poc.jsonl
2>&1 | tee credential-error-leak.txtSearch the response:
bash
grep -nE
'MCP POC USER 7391|MCP POC PASS 7391'
credential-error-leak.txtObserved result
The complete URL is exposed in the MCP logging notification:
text
Tool execution error: Configuration Issues: SEARXNG URL invalid protocol for "ftp://MCP POC USER 7391:MCP POC PASS 7391@example.invalid": ftp:It is also returned directly in the JSON-RPC error:
json
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32603,
"message": "Configuration Issues: SEARXNG URL invalid protocol for "ftp://MCP POC USER 7391:MCP POC PASS 7391@example.invalid": ftp:"
}
}The raw username and password are therefore exposed through both logging and protocol responses.
Impact
This is a sensitive credential disclosure vulnerability.
The following parties may obtain the credentials:
- A connected MCP client receiving logging notifications.
- A client capable of invoking a tool and receiving JSON-RPC errors.
- A user or process with access to captured stderr output.
- A centralized logging or monitoring system collecting application logs.
- Other users with access to shared log files or container logs.
The exposed credentials may allow an attacker to authenticate directly to the configured SearXNG instance.
Depending on the SearXNG deployment and the permissions associated with the account, this may allow:
- Unauthorized use of a private SearXNG service.
- Access to functionality restricted through Basic Authentication.
- Consumption of private server resources.
- Exposure of information available only to authenticated users.
- Further account compromise where the credentials have been reused.
The default STDIO transport limits the exposure to the connected parent MCP client and local logging environment. However, MCP clients should not receive upstream service credentials, and the project security documentation explicitly treats credentials embedded in
SEARXNG URL as secrets that must be redacted.Suggested mitigation
Apply
redactSearxngInstanceUrl() before including any SearXNG URL in console or MCP logging:typescript
const redactedInstances = getSearxngInstances()
.map(redactSearxngInstanceUrl);
logMessage(
mcpServer,
"info",
`SearXNG URLs: ${
redactedInstances.length > 0
? redactedInstances.join("; ")
: "not configured"
}`
);Do not include raw configuration values in validation errors. A generic error can be returned instead:
typescript
return `SEARXNG URL entry has an unsupported protocol: ${url.protocol}`;For malformed URLs:
typescript
return "SEARXNG URL contains an invalid URL";The following additional changes are recommended:
- Redact URLs before writing them to stderr.
- Redact secrets before sending MCP logging notifications.
- Avoid including raw environment-variable values in exceptions.
- Avoid returning detailed stack traces containing secrets to MCP clients.
- Mark
SEARXNG URLas secret in.mcp/server.json:
json
"isSecret": true- Add regression tests that assert usernames and passwords never appear in:
- stderr output
- MCP logging notifications
- JSON-RPC error responses
- stack traces
- configuration resources
Fix
Generation of Error Message Containing Sensitive Information
Insertion into Log File
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Mcp-Searxng