[ ⌘K ]
← BACK TO SEARCH

neotty/mcp-client-browser

critical

TypeScript SDK for using large language models with an MCP server directly in the browser, powered by Cherry Studio's prompt templates.

MCP server (purpose undetermined)

purpose: MCP server (purpose undetermined)threat: network exposed
TypeScript5May 20, 2026May 20, 2026GITHUB
5/20/2026
high1 finding
src/client/browser-sse.ts
14constructor(
15    mcpUrls: (URL | { url: URL, headers?: Record<string, string>, name?: string }) | (URL | { url: URL, headers?: Record<string, string>, name?: string })[],
16    openAIConfig?: {
17        baseUrl?: string,
18        apiKey?: string,
19        model?: string,
20    }
21) {
22    const urlConfigArray = Array.isArray(mcpUrls) ? mcpUrls : [mcpUrls];
23    this.mcpConnections = urlConfigArray.map((item, index) => {
24        if (item instanceof URL) {
25            return {
26                url: item,
27                client: new Client({
28                    name: `sse-client-${index}`,
29                    version: '1.0.0'
30                }),
31                name: item.hostname
32            };
33        } else {
34            return {
35                url: item.url,
36                headers: item.headers || {},
37                client: new Client({
38                    name: `sse-client-${index}`,
39                    version: '1.0.0'
40                }),
41                name: item.name || item.url.hostname
42            };
43        }
44    });
45}
src/index.ts:1src/client/index.ts:1src/client/browser-sse.ts:1

// Exploitable if an attacker can influence the mcpUrls parameter (e.g., via prompt injection or configuration manipulation).

The MCP client accepts arbitrary URLs for SSE connections without any validation or allowlisting. An attacker who can control the input (e.g., via prompt injection or configuration) can make the client connect to any external server, potentially exfiltrating data or performing SSRF attacks.

ImpactAn attacker could redirect the MCP client to a malicious SSE server, exfiltrate sensitive data (e.g., API keys, chat history), or perform SSRF attacks against internal services.

FixImplement a whitelist of allowed SSE server URLs or validate URLs against a known pattern. Restrict connections to trusted servers only.

high1 finding
src/client/browser-sse.ts
55if (openAIConfig?.baseUrl && (openAIConfig?.apiKey !== undefined)) {
56    this.openAI = new OpenAI({
57        apiKey: openAIConfig.apiKey || '',  // 允许空字符串
58        baseURL: openAIConfig.baseUrl,
59        dangerouslyAllowBrowser: true
60    });
61    this.openAI.apiModel = openAIConfig.model || "gpt-3.5-turbo";
62}
src/index.ts:1src/client/index.ts:1src/client/browser-sse.ts:1

// Exploitable if an attacker can read process memory or if the client runs in a browser environment where secrets are exposed.

The OpenAI API key is passed in plaintext to the constructor and stored in memory. If an attacker gains access to the process memory or can exploit a vulnerability to read memory, the API key could be compromised. Additionally, the key is used in browser context with dangerouslyAllowBrowser: true, which exposes it to client-side attacks.

ImpactAn attacker could extract the OpenAI API key and use it to make unauthorized API calls, incurring costs or accessing sensitive data.

FixAvoid storing API keys in client-side code. Use a backend proxy to handle API calls, or use environment variables and server-side authentication. Remove dangerouslyAllowBrowser: true.

medium1 finding
src/client/browser-sse.ts
148async processQuery(
149    userSystemPrompt: string,
150    query: string,
151    useHistory: boolean = true,
152    maxTokens?: number,
153    topP?: number,
154    temperature?: number
155): Promise<string> {
156    if (!this.openAI) {
157        throw new Error("OpenAI API key not provided. Cannot process query.");
158    }
159    userSystemPrompt = userSystemPrompt || "";
160    const response = await this.listTools();
161    const systemPrompt = BuildSystemPrompt(userSystemPrompt, response.tools as unknown as MCPTool[]);
162    let messages: MessageContent[];
163    if (!useHistory || this.chatHistory.length === 0) {
164        messages = [
165            { role: "system", content: systemPrompt },
166            { role: "user", content: query }
167        ];
168    } else {
169        messages = [...this.chatHistory];
170        if (messages.length > 0 && messages[0].role === "system") {
171            messages[0].content = systemPrompt;
172        } else {
173            messages.unshift({ role: "system", content: systemPrompt });
174        }
175        messages.push({ role: "user", content: query });
176    }
src/index.ts:1src/client/index.ts:1src/client/browser-sse.ts:1

// Exploitable if an attacker can control the userSystemPrompt or query parameters (e.g., via a web interface or API).

The user-supplied system prompt and query are passed directly to the LLM without any sanitization or filtering. An attacker could inject malicious instructions that override the system prompt or manipulate the LLM to perform unintended actions, such as calling tools in unexpected ways.

ImpactAn attacker could perform prompt injection attacks to manipulate the LLM's behavior, potentially leading to unauthorized tool calls, data exfiltration, or other malicious actions.

FixSanitize and validate user inputs before passing them to the LLM. Use a separate, immutable system prompt that cannot be overridden. Implement input filtering to block known injection patterns.

medium1 finding
src/client/browser-sse.ts
252const result = await clientForTool.callTool({
253    name: toolName,
254    arguments: toolArgs
255});
src/index.ts:1src/client/index.ts:1src/client/browser-sse.ts:1

// Exploitable if the external MCP server is untrusted or compromised, or if an attacker can influence tool selection via prompt injection.

The tool arguments (toolArgs) are passed directly to the external MCP server without any validation or sanitization. If the external server is malicious or compromised, it could execute arbitrary commands or return malicious data. Additionally, if the tool name is manipulated, it could call unintended tools.

ImpactAn attacker could inject malicious arguments that cause the external MCP server to perform unintended actions, such as executing shell commands or reading sensitive files.

FixValidate tool names against a known list. Sanitize and validate arguments before passing them to external servers. Consider using a schema validation library.

shell.execenv.exposure
80
LLM-based
high findings+50
medium findings+30