GitHub Advisoryadvisory · PyPI

GHSA-hc5v-gxvj-58wh PraisonAI: MCP HTTP-stream transport is unauthenticated by default, exposing tool enumeration and an unvalidated tool-call surface

HIGH Published 2026-10-08 Modified 2026-10-08 Official page ↗
Aliases
CVE-2026-61427
Ecosystem
PyPI
Packages
praisonai
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weaknesses
CWE-20, CWE-306, CWE-862
Reviewed
2026-10-08

Affected packages

• PyPI praisonai: < 4.6.78 → fixed in 4.6.78

Description

Summary PraisonAI's MCP HTTP-stream server authenticates requests only when an API key is configured; the CLI defaults `--api-key` to `None`, so `praisonai mcp serve --transport http-stream` exposes the full MCP surface unauthenticated. A request with no `Authorization` (and no `Origin`) can `initialize` and `tools/list` (~50 tools), and the dispatcher forwards tool-call arguments to handlers without validating them against the advertised `inputSchema`. Runtime-confirmed for unauthenticated `initialize`/`tools/list` and the dispatcher schema-bypass. This is not an RCE/file-read in 4.6.63 — `workflow.run`/`workflow.run_file` are runtime-refuted (adapter regression). Severity Medium–High. Details Affected component • Package: `praisonai` 4.6.63. Files: `src/praisonai/praisonai/mcp_server/transports/http_stream.py`, `mcp_server/cli.py`, `mcp_server/server.py` (dispatcher). Vulnerable code / root cause Path: `src/praisonai/praisonai/mcp_server/transports/http_stream.py` Function: `mcp_post` / `_validate_origin` Snippet: ```python if self.api_key: # auth applied ONLY when api_key is set auth_header = request.headers.get("Authorization", "") if not auth_header.startswith("Bearer ") or auth_header[7:] != self.api_key: return JSONResponse({"error": "Unauthorized"}, status_code=401) _validate_origin: returns True when the Origin header is absent ``` Issue: with `api_key=None`, no auth check runs; a missing `Origin` header is allowed, so non-browser clients (curl/Burp) are not blocked. Path: `src/praisonai/praisonai/mcp_server/cli.py` Function: `cmd_serve` (argparse) Snippet: ```python parser.add_argument("--api-key", default=None) # unauthenticated by default ``` Path: `src/praisonai/praisonai/mcp_server/server.py` Function: `_handle_tools_call` Snippet: ```python result = await tool.handler(arguments) # arguments forwarded without inputSchema validation ``` Issue: attacker-controlled `arguments` are passed straight to the handler; the dispatcher does not validate them against the tool's advertised `inputSchema`. The only thing rejecting undeclared keys is the handler's own Python signature. Attack flow 1. Operator runs `praisonai mcp serve --transport http-stream` (no `--api-key`). 2. Attacker (no auth, no Origin) sends `initialize` → session; `tools/list` → enumerates ~50 tools; `tools/call` → arguments pass through unvalidated. Why existing protection is bypassed Auth is opt-in (only added when an api key is set); missing `Origin` is allowed; the dispatcher does not enforce `inputSchema`. Security boundary Unauthenticated access to the MCP tool surface. Default bind `127.0.0.1` (any local process / multi-user host; remote only if `--host 0.0.0.0`). Scope limits (do not overclaim) • `praisonai.workflow.run` / `workflow.run_file` are runtime-refuted in 4.6.63: the adapter calls `AgentsGenerator(...)` missing the required `config_list` argument → errors before any execution/file open. Several other tool adapters also error at runtime. No unauthenticated RCE/arbitrary-file-open via these tools at HEAD. • MCP `knowledge.add` file read is broken (see `FT-01_Knowledge_FileRead_Negative_Report.md`). Proof of Concept Environment Real MCP HTTP-stream server (`api_key=None`) in a local runtime (`127.0.0.1:18090`). Runnable assets: `PraisonAI-Runtime-Repro\runtime-files\` (`docker-compose.mcp.yml`). MCP requests use `Accept: application/json` + header `Mcp-Session-Id`. Steps to reproduce 1. `MCP-Initialize`: `POST /mcp` initialize (no Authorization) → `200` + `mcp-session-id`. 2. `MCP-Tools-List-NoAuth`: `POST /mcp` `tools/list` with that session id → `200` + ~50 tools. 3. `MCP-Schema-Bypass`: `tools/call` with an undeclared extra argument (`__undeclared_evil_param__`). Expected result The transport requires authentication; the dispatcher validates arguments against `inputSchema`. Actual result • `initialize`/`tools/list` succeed with no auth and no Origin header. • The undeclared argument reaches the handler (`got an unexpected keyword argument '__undeclared_evil_param__'`), proving no schema validation at the dispatcher. Screenshots Screenshots Unauthenticated MCP initialize A POST request to `/mcp` with method `initialize` succeeds without an `Authorization` header. The server returns HTTP 200 OK, exposes MCP capabilities, and issues an `mcp-session-id` to the unauthenticated client. Unauthenticated MCP tools/list After initialization, the same unauthenticated MCP session can call `tools/list` using only the issued `Mcp-Session-Id`. The server returns HTTP 200 OK and exposes tool names, schemas, and annotations. MCP tool-call schema bypass** The unauthenticated MCP client calls `tools/call` with an extra argument not declared in the tool schema. Instead of rejecting the schema-violating input at the dispatcher layer, the unexpected parameter reaches the Python handler and causes an `unexpected keyword argument` error. This confirms incomplete input-schema enforcement for tool calls. Impact Unauthenticated tool enumeration and tool-call surface; LLM-key/cost abuse and data access via whichever tools function (impact currently limited by several broken adapters and the default loopback bind). No confirmed unauthenticated RCE/file-read in 4.6.63.

Related

Alias · CVE (1)

  • CVE-2026-61427 PraisonAI before 4.6.78 exposes the MCP HTTP-stream transport without authentication by default: the CLI --api-key option defaults to None,… vulnerability

Weakness · CWE (3)

  • CWE-20 Improper Input Validation weakness
  • CWE-306 Missing Authentication for Critical Functionality weakness
  • CWE-862 Missing Authorization weakness

References