Get a Demo

Let's Patch It!

Book a short call with one our specialists, we'll walk you through how Endor Patches work, and ask you a few questions about your environment (like your primary programming languages and repository management). We'll also send you an email right after you fill out the form, feel free to reply with any questions you have in advance!

CVE

GHSA-x227-pf99-vffg

PraisonAI: MCP SSE transport binds 0.0.0.0 with no authentication and no Origin validation; bundled SecurityConfig is never wired in
Back to all
CVE

GHSA-x227-pf99-vffg

PraisonAI: MCP SSE transport binds 0.0.0.0 with no authentication and no Origin validation; bundled SecurityConfig is never wired in

The MCP SSE server started via ToolsMCPServer.runsse() / launchtoolsmcpserver(transport="sse")

binds to 0.0.0.0 by default and builds its Starlette application with no authentication middleware

and no Origin-header validation. The module mcp/mcp_security.py provides exactly the needed controls

(origin validation, DNS-rebinding detection, auth-header enforcement, a SecurityConfig), but none of

these functions are ever called by any transport — they are dead code. Any host that can reach the

port can list and invoke every registered tool with no credentials, and a victim's browser can drive

the same calls against a localhost instance via DNS rebinding.

Affected code: src/praisonai-agents/praisonaiagents/mcp/mcp_server.py

  • run_sse defaults host to all interfaces (line 245) and builds the app with only debug and routes
  • no middleware= and no per-route auth/origin gate (lines ~271-289):

      app = Starlette(debug=self._debug, routes=[

          Route(ssepath, endpoint=handlesse),                          # "/sse"

          Mount(messagespath, app=ssetransport.handlepostmessage),   # "/messages/"

      ])

      uvicorn.run(app, host=host, port=port)

  • launchtoolsmcp_server also defaults host="0.0.0.0" (line 301).

src/praisonai-agents/praisonaiagents/mcp/mcp_security.py defines but the transports never call:

  • isvalidorigin (line 30), ispotentialdnsrebinding (line 110), validateauth_header (line 167),

  SecurityConfig.isoriginallowed (line 236). These symbols are referenced only inside mcp_security.py

  and the init re-export. (mcp_websocket.py's auth references are CLIENT-side, not server validation.)

Impact:

launchtoolsmcp_server(transport="sse") is the documented path for exposing tools over MCP. With the

defaults above it is an unauthenticated, network-reachable tool-execution endpoint. Blast radius equals

the capabilities of the registered tools; with file/shell/code-exec tools this is RCE. With no Origin

check, a malicious page the victim merely visits can rebind its hostname to 127.0.0.1 and issue the

JSON-RPC calls cross-origin against a developer's local server.

Proof of concept:

Static proof (AST analysis of unmodified source):

  Check 1 - runsse(host='0.0.0.0'); launchtoolsmcpserver(host='0.0.0.0')  -> EXPOSED

  Check 2 - Starlette(...) kwargs: ['debug','routes']  -> NO middleware= (no auth/origin gate)

  Check 3 - isvalidorigin / ispotentialdnsrebinding / validateauth_header / SecurityConfig

            never called by any transport  -> DEAD CODE

Live exploitation against a running server:

  curl -N http://VICTIM:8080/sse

  #   event: endpoint  / data: /messages/?session_id=<sid>

  curl -X POST "http://VICTIM:8080/messages/?session_id=<sid>" -H 'Content-Type: application/json' \

    -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05",

         "capabilities":{},"clientInfo":{"name":"x","version":"1"}}}'

  curl -X POST "http://VICTIM:8080/messages/?session_id=<sid>" -H 'Content-Type: application/json' \

    -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"<tool>","arguments":{...}}}'

No Authorization header anywhere. Browser DNS-rebinding variant drives the same calls cross-origin.

Remediation:

Wire in the existing mcp_security.py controls and fix defaults:

  • Default run_sse(host="127.0.0.1"); require explicit opt-in to bind 0.0.0.0.
  • Attach Starlette middleware calling isvalidorigin / ispotentialdns_rebinding; reject bad origins.
  • Enforce validateauthheader when SecurityConfig.requireauth; default requireauth=True (and

  allowmissingorigin=False) for any non-loopback bind.

Distinct from prior advisories:

The accepted MCP advisories are tool-handler bugs — tools/call path traversal -> .pth RCE

(GHSA-9mqq-jqxf-grvw) and unauthenticated file read via workflow.show/validate (GHSA-9cr9-25q5-8prj).

This is a transport-layer missing-auth/exposure: the SSE server never enforces auth or Origin validation

and ignores the security module the codebase ships. Closest in spirit to the default-insecure pattern

(GHSA-8444 / 86qc) but a different server and a different root cause (unwired controls, not an unset env var).

Package Versions Affected

Package Version
patch Availability
No items found.

Automatically patch vulnerabilities without upgrading

Fix Without Upgrading
Detect compatible fix
Apply safe remediation
Fix with a single pull request

CVSS Version

Severity
Base Score
CVSS Version
Score Vector
C
H
U
-
C
H
U
0
-
3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
C
H
U
-

Related Resources

No items found.

References

https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-x227-pf99-vffg, https://github.com/MervinPraison/PraisonAI

Severity

9.8

CVSS Score
0
10

Basic Information

Base CVSS
9.8
EPSS Probability
0%
EPSS Percentile
0%
Introduced Version
0
Fix Available
1.6.59

Fix Critical Vulnerabilities Instantly

Secure your app without upgrading.
Fix Without Upgrading