GitHub Security Advisory: GHSA-x462-jjpc-q4q4
Package: praisonaiagents (PIP)
Severity: HIGH (CVSS 8.1)
CWE: CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains
Vulnerable versions: < 4.5.128
Patched in: 4.5.128

Summary: PraisonAI: Cross-Origin Agent Execution via Hardcoded Wildcard CORS and Missing Authentication on AGUI Endpoint

Details:
## Summary

The AGUI endpoint (`POST /agui`) has no authentication and hardcodes `Access-Control-Allow-Origin: *` on all responses. Combined with Starlette/FastAPI's Content-Type-agnostic JSON parsing, any website a victim visits can silently trigger arbitrary agent execution against a locally-running AGUI server and read the full response, including tool execution results and potentially sensitive data from the victim's environment.

## Details

The vulnerability is a combination of three issues in `src/praisonai-agents/praisonaiagents/ui/agui/agui.py`:

**1. No authentication (line 124-125):**
```python
@router.post("/agui")
async def run_agent_agui(run_input: RunAgentInput):
```
The endpoint accepts any request. `RunAgentInput` (defined in `types.py:159-165`) has no auth token, API key, or session validation field. No middleware or dependencies are attached to the router (line 111).

**2. Hardcoded wildcard CORS (line 131-141):**
```python
return StreamingResponse(
    event_generator(),
    media_type="text/event-stream",
    headers={
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
        "Access-Control-Allow-Headers": "*",
    },
)
```
The `Access-Control-Allow-Origin: *` header is hardcoded in the library code. Library consumers cannot override this without patching the source.

**3. CORS preflight bypass via Starlette's Content-Type-agnostic parsing:**
Starlette's `Request.json()` (used internally by FastAPI for Pydantic body models) calls `json.loads(await self.body())` without verifying that `Content-Type` is `application/json`. A browser POST with `Content-Type: text/plain` is classified as a CORS "simple request" per the Fetch specification — no preflight OPTIONS request is sent. Since the JSON body is still parsed successfully, the request executes normally.

**Attack flow:**
1. Victim runs an AGUI server locally (the documented usage pattern per the class docstring at lines 42-50)
2. Victim visits an attacker-controlled website
3. Attacker's JavaScript sends `POST` to `http://localhost:8000/agui` with `Content-Type: text/plain` containing a JSON body — this is a simple request, no preflight
4. FastAPI parses the JSON body into `RunAgentInput`, the agent executes with full tool capabilities
5. The streaming response includes `Access-Control-Allow-Origin: *`, so the browser permits the attacker's JavaScript to read the response
6. Attacker exfiltrates the agent's output, including any tool execution results

## PoC

**Prerequisites:** A locally running AGUI server (the default setup from documentation):

```python
# server.py - standard AGUI setup
from praisonaiagents import Agent
from praisonaiagents.ui.agui import AGUI
from fastapi import FastAPI
import uvicorn

agent = Agent(name="Assistant", role="Helper", goal="Help users")
agui = AGUI(agent=agent)
app = FastAPI()
app.include_router(agui.get_router(