GHSA-p75f-6fp4-p57w
Unauthenticated UI MCP connect endpoint executes attacker-chosen local commands
PraisonAI — bundled UI (MCP management)[pip · praisonai]
PraisonAI's bundled UI shipped an MCP management endpoint with no authentication — a single POST let any network-reachable client start a process of its choosing on the host.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H> Overview
PraisonAI is a multi-agent framework whose optional UI extras ship a bundled web app (PraisonAIUI) for managing agents and their MCP connections. In affected versions the UI's MCP client-management API was exposed without authentication, and the UI commands bind to all interfaces by default.
The `POST /api/mcp/connect` route accepted a caller-supplied `command` and `args` and handed them to the MCP stdio client, which launches that command as a local process under the UI service account. A remote, unauthenticated client could therefore run an arbitrary program on the host.
Fixed in PraisonAI 4.6.59. This writeup summarizes the public, GitHub-reviewed advisory; the vulnerable versions are no longer current.
> Root cause
The exposure came from the composition of a few defaults rather than a single line: MCP is a base dependency, the UI extras pull in a server whose authentication is opt-in, and the UI commands publish that server to the network by default.
- The `ui` / `claw` extras pull in the PraisonAIUI server, whose `create_app()` defaults to `require_auth=False`; its auth middleware only enforces when `AUTH_ENFORCE=true`.
- `praisonai ui`, `praisonai ui agents` and `praisonai claw` bind to 0.0.0.0 by default, so the app is reachable off-host.
- `POST /api/mcp/connect` reads attacker JSON, and when a `command` is present it selects the stdio transport and constructs the client with that command and args.
- Connecting the client invokes the MCP stdio transport, which starts the chosen process — turning an HTTP body into local process execution.
> Representative request
As published in the advisory, the crux of the finding is a single unauthenticated request. A benign `touch` stands in for the payload; in a real attack the command could be a shell, a credential-exfiltration command, or any long-lived process.
POST /api/mcp/connect HTTP/1.1
Content-Type: application/json
{
"name": "evil",
"command": "/usr/bin/touch",
"args": ["/tmp/pwned-by-ui-mcp"]
}> Impact
This is unauthenticated remote command execution in the UI service's process context. An attacker who can reach the port can run local commands as the service user — enabling secret and file exfiltration, tampering, service disruption, and persistence via a long-lived process.
Because the default binding is 0.0.0.0 and authentication is off unless explicitly enabled, any deployment following the documented quickstart was reachable by any client on the network, which is what puts the finding at the top of the Critical range.
> The fix & hardening
Resolved in PraisonAI 4.6.59. The remediation direction closes both halves of the bug — the missing authentication and the caller-controlled process launch:
- Require authentication and authorization on the MCP management routes.
- Remove caller-controlled local command and argument execution from remote HTTP APIs.
- Make externally reachable UI binding opt-in, or require authentication whenever it is exposed.
- Back process-launched MCP servers with trusted local configuration or an administrator-managed allowlist rather than request input.
> Classification & disclosure status
Scored Critical (CVSS 9.8) and classified as CWE-78 (OS Command Injection) combined with CWE-306 (Missing Authentication for Critical Function). The advisory is public and GitHub-reviewed in the global GitHub Advisory Database.
A CVE has been assigned for this advisory, but its public CVE Registry record is still propagating. The identifier is intentionally withheld on this page until that record is live — the finding is presented by its public GHSA.
> Disclosure timeline
- 2026-06-02Advisory opened; credited as reporter.
- 2026-06-17PraisonAI accepted and published the advisory and requested a CVE.
- 2026-06-18GitHub released the advisory to the global GitHub Advisory Database.
- 2026-06-23A CVE was assigned — identifier withheld pending public Registry propagation.