Skip to content

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

Critical severity GitHub Reviewed Published Jun 17, 2026 in MervinPraison/PraisonAI

Package

pip praisonaiagents (pip)

Affected versions

< 1.6.59

Patched versions

1.6.59

Description

The MCP SSE server started via ToolsMCPServer.run_sse() / launch_tools_mcp_server(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(sse_path, endpoint=handle_sse), # "/sse"
      Mount(messages_path, app=sse_transport.handle_post_message), # "/messages/"
      ])
      uvicorn.run(app, host=host, port=port)
  • launch_tools_mcp_server also defaults host="0.0.0.0" (line 301).

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

  • is_valid_origin (line 30), is_potential_dns_rebinding (line 110), validate_auth_header (line 167),
    SecurityConfig.is_origin_allowed (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:
launch_tools_mcp_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 - run_sse(host='0.0.0.0'); launch_tools_mcp_server(host='0.0.0.0') -> EXPOSED
Check 2 - Starlette(...) kwargs: ['debug','routes'] -> NO middleware= (no auth/origin gate)
Check 3 - is_valid_origin / is_potential_dns_rebinding / validate_auth_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=

curl -X POST "http://VICTIM:8080/messages/?session_id=" -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=" -H 'Content-Type: application/json'
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"","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 is_valid_origin / is_potential_dns_rebinding; reject bad origins.
  • Enforce validate_auth_header when SecurityConfig.require_auth; default require_auth=True (and
    allow_missing_origin=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).

References

@MervinPraison MervinPraison published to MervinPraison/PraisonAI Jun 17, 2026
Published to the GitHub Advisory Database Jun 18, 2026
Reviewed Jun 18, 2026

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

EPSS score

Weaknesses

Missing Authentication for Critical Function

The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources. Learn more on MITRE.

Reliance on Reverse DNS Resolution for a Security-Critical Action

The product performs reverse DNS resolution on an IP address to obtain the hostname and make a security decision, but it does not properly ensure that the IP address is truly associated with the hostname. Learn more on MITRE.

Binding to an Unrestricted IP Address

The product assigns the address 0.0.0.0 for a database server, a cloud service/instance, or any computing resource that communicates remotely. Learn more on MITRE.

CVE ID

No known CVE

GHSA ID

GHSA-x227-pf99-vffg

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.