# npm PraisonAI MCPServer exposes unauthenticated HTTP tools/call

npm praisonai MCPServer HTTP transport lacks any auth, letting any network client list and invoke registered MCP tools via JSON-RPC tools/call.

- Payout: Research
- Severity: critical
- Program: PraisonAI
- Found by: rexpository
- Disclosed: 2026-06-18
- CVE: CVE-2026-57139
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-j4f3-55x4-r6q2
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-j4f3-55x4-r6q2
- Tags: area:ai domain:ai domain:web3 impact:data-leak impact:rce kind:research platform:ghsa sev:critical tech:llm tech:nodejs technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration

**Target:** npm praisonai TypeScript MCPServer HTTP JSON-RPC transport (src/mcp/server.ts)
**Root cause:** startHttp() parses every POST body and forwards it to handleRequest() with no auth check; MCPServerConfig has no auth field and the shipped MCPSecurity manager is never wired in. listen(port) also binds to the unspecified address (::).
**Steps:**
1. Install npm praisonai 1.5.0-1.7.1 and start the exported MCPServer: `await server.start({ port: 3000 })`
2. Observe bind address is `{ address: "::", family: "IPv6" }` (all interfaces)
3. POST JSON-RPC `initialize` to the port; returns 200 without credentials
4. POST `tools/list`; returns registered tools (e.g. `admin_reset_marker`)
5. POST `tools/call` with the tool name and args; handler executes and returns `invoked:NO_AUTH_MARKER`
6. Repeat with `Authorization: Bearer invalid`; still 200 and tool invoked
**How found:** Code review of the TypeScript MCP server: noticed MCPServerConfig exposes no auth/security option, startHttp() ignores the Authorization header, and the package already ships an MCPSecurity manager (with createApiKeyPolicy) that the HTTP path never references — a guard-coverage gap versus documented API-key requirements and prior hardening that bound API servers to 127.0.0.1.
**Exploitation:** Any client reaching the HTTP port sends JSON-RPC POSTs directly to handleRequest(); no credentials needed and invalid bearer tokens are ignored. tools/call invokes registered handlers with server process privileges and server-side credentials (filesystem, DB, API clients, deployment, email/Slack, code execution), and resources/read / prompts/get disclose registered data.
**Escalation:** Impact scales with registered tools: handlers wrapping filesystem, DB, deployment or code-execution actions turn unauthenticated RPC into those privileged operations; binding to :: widens reachability beyond loopback.
**Insight:** When a package ships a security module (MCPSecurity.check, createApiKeyPolicy) but the transport never imports it, that unwired guard is the bug: grep for security/auth classes and confirm each request path actually calls them. Also check listen(port) without a host — Node binds :: (all interfaces), not loopback.

## Proof of concept (copied exactly from the original report)

**Unauthenticated tools/call invokes registered tool**

```
"callNoAuth": {
    "status": 200,
    "json": {
      "result": {
        "content": [
          {
            "text": "invoked:NO_AUTH_MARKER"
```

**Invalid bearer token still invokes tool**

```
"callBadAuth": {
    "status": 200,
    "json": {
      "result": {
        "content": [
          {
            "text": "invoked:BAD_AUTH_MARKER"
```

**Version sweep confirming no-auth tool call**

```
1.5.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.5.4: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.6.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.7.0: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
1.7.1: mcpServerExported=true, hasDistMcpServer=true, noAuthToolCallInvoked=true, bindAddress=::
```

