BACK TO SEARCH
andrea9293/mcp-client-templatecritical

A template for building MCP (Model Context Protocol) client applications, featuring a Vite + TypeScript frontend and an Express backend. Includes OAuth2.1 authentication and ready-to-use APIs for managing and interacting with MCP servers. Easily extensible for custom workflows and integrations.

This MCP client template provides a web interface to manage and interact with MCP servers. It allows users to add MCP servers (stdio, HTTP stream, SSE...

purpose: This MCP client template provides a web interface threat: network exposed
TypeScript · 8 · May 21, 2026 · May 21, 2026 · GITHUB ↗
RISK SCORE
0/ 100 risk
high findings+75
medium findings+60
capped at100
VULNERABILITY ANALYSIS · 7 findings in 7 blocks3 HIGH · 4 MEDIUM
HIGH1 finding
server/index.ts:112
112if (type === 'httpstream' || type === 'sse') {
113    const TransportClass = type === 'httpstream' ? StreamableHTTPClientTransport : SSEClientTransport;
114    const transport = new TransportClass(new URL(command), { authProvider: oauthProvider });
115    ...
116}
server/index.ts:112

// Network-exposed MCP backend; any user can add a server with a malicious URL.

EXPLAINThe command field (which is user-controlled via /add-server) is used directly as a URL to create a TransportClass instance. No validation is performed on the URL, allowing an attacker to specify arbitrary URLs, including internal network addresses (e.g., http://localhost:8080, http://169.254.169.254/latest/meta-data/). This enables Server-Side Request Forgery (SSRF) attacks.
IMPACTAn attacker can make the server send requests to arbitrary internal or external hosts, potentially accessing sensitive internal services, cloud metadata endpoints, or performing port scanning.
FIXValidate the URL against a whitelist of allowed hosts and schemes. Restrict to HTTPS and known MCP server endpoints.
HIGH1 finding
server/index.ts:38
38app.post('/add-server', (req, res) => {
39    const { id, command, type, args } = req.body;
40    if (!id || !command || !type) {
41        res.status(400).json({ error: 'Missing required fields' });
42        return;
43    }
44    ...
45    serversJson.servers[id] = {
46        command,
47        type,
48        args: Array.isArray(args) ? args : []
49    };
50    try {
51        fs.writeFileSync(serversPath, JSON.stringify(serversJson, null, 2), 'utf-8');
52        res.json({ success: true });
53    } catch (err) {
54        res.status(500).json({ error: 'Cannot write server config' });
55    }
56});
server/index.ts:38

// Network-exposed MCP backend; any user can call /add-server and execute arbitrary commands.

EXPLAINThe /add-server endpoint accepts arbitrary command and args from the user without any validation or sanitization. This allows an attacker to register a malicious MCP server that executes arbitrary commands on the host system when the server is started (via stdio transport). The command is later used in StdioClientTransport which spawns a child process.
IMPACTAn attacker can execute arbitrary commands on the server by adding a server with a malicious command (e.g., 'bash', 'nc', 'curl'). This leads to full remote code execution on the backend server.
FIXValidate the command against a whitelist of allowed executables. Restrict args to safe values. Consider not allowing arbitrary command execution from user input.
HIGH1 finding
server/index.ts:136
136app.post('/mcp', async (req, res) => {
137    const { server, command, args: argsOverride } = req.body;
138    ...
139    let serverConfig = serversJson[server];
140    if (!serverConfig && serversJson.servers && serversJson.servers[server]) {
141        serverConfig = serversJson.servers[server];
142    }
143    if (!serverConfig) {
144        res.status(404).json({ error: 'Server not found' });
145        return;
146    }
147    if (argsOverride && Array.isArray(argsOverride)) {
148        serverConfig = { ...serverConfig, args: argsOverride };
149    }
150    serverConfig = { name: server, ...serverConfig }
151    globalServersJson[server] = serverConfig;
152    let connection;
153    try {
154        connection = await autoDetectTransport(serverConfig);
155    } catch (err) { ... }
server/index.ts:136

// Network-exposed MCP backend; any user can call /mcp with a malicious server name or argsOverride.

EXPLAINThe /mcp endpoint uses the server configuration (including command and args) from the stored JSON file, which can be set via /add-server without validation. Additionally, argsOverride from the request body can override the args, allowing an attacker to inject arbitrary arguments into the spawned process. This leads to arbitrary command execution.
IMPACTAn attacker can execute arbitrary commands on the server by first adding a malicious server or by providing argsOverride that injects malicious arguments into the command.
FIXValidate the command and args before spawning the process. Consider not allowing arbitrary args override from user input.
MEDIUM1 finding
server/index.ts:38
38app.post('/add-server', (req, res) => {
39    const { id, command, type, args } = req.body;
40    ...
41});
42app.get('/servers', (req, res) => { ... });
43app.post('/mcp', async (req, res) => { ... });
server/index.ts:38

// Network-exposed MCP backend; no authentication required.

EXPLAINAll API endpoints (/add-server, /servers, /mcp, /oauth/callback) are publicly accessible without any authentication or authorization. Any network attacker can call these endpoints.
IMPACTAn attacker can add malicious servers, list servers, call tools, and interact with OAuth flows without any credentials.
FIXImplement authentication (e.g., API key, JWT) for all endpoints.
MEDIUM1 finding
server/index.ts:120
120const tokens = globalServersJson.get(serverConfig.name)?.oauthProvider?.getTokens();
121console.log("Access Token:", JSON.stringify(tokens, null, 2));
server/index.ts:120

// Network-exposed MCP backend; logs may be accessible to attackers.

EXPLAINOAuth access tokens are logged to the console in plaintext. This exposes sensitive credentials to anyone with access to the server logs.
IMPACTAn attacker with access to server logs can obtain OAuth tokens and impersonate the user or access protected resources.
FIXRemove console.log of tokens or redact sensitive fields before logging.
MEDIUM1 finding
server/authTokensStore.ts:29
29setServerTokens(serverName: string, tokens: any) {
30    this.data.tokens[serverName] = {
31        tokens,
32        lastConnected: new Date().toISOString(),
33        connected: true
34    };
35    this.save();
36}
server/authTokensStore.ts:29

// Network-exposed MCP backend; file system access may be possible via other vulnerabilities.

EXPLAINOAuth tokens are stored in a JSON file (auth-tokens.json) in plaintext without encryption. An attacker with file system access can read these tokens.
IMPACTAn attacker with access to the server's file system can steal OAuth tokens and gain unauthorized access to MCP servers.
FIXEncrypt the tokens at rest using a secure encryption mechanism or use a secure credential store.
MEDIUM1 finding
server/index.ts:56
56serversJson.servers[id] = {
57    command,
58    type,
59    args: Array.isArray(args) ? args : []
60};
61try {
62    fs.writeFileSync(serversPath, JSON.stringify(serversJson, null, 2), 'utf-8');
63    res.json({ success: true });
64} catch (err) { ... }
server/index.ts:56

// Network-exposed MCP backend; low risk but should be fixed.

EXPLAINThe server ID is used as a key in the JSON object but is not validated. While it does not directly affect file paths (serversPath is fixed), the ID could contain special characters that might cause issues in other parts of the application (e.g., when used in logs or displayed). However, the main risk is that the ID is later used in globalServersJson and could be used in other contexts.
IMPACTLimited direct impact, but could lead to injection in logs or other outputs.
FIXValidate server ID to only allow alphanumeric characters and hyphens/underscores.
5/21/2026
Findings are produced by automated LLM analysis and may include false positives or miss issues. Verify independently before acting.