PT-2026-53545 · Pypi · Praisonai

Published

2026-06-29

·

Updated

2026-06-29

CVSS v3.1

9.1

Critical

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

Summary

OAuthManager.validate token() returns True for any token not found in its internal store, which is empty by default. Any HTTP request to the MCP server with an arbitrary Bearer token is treated as authenticated, granting full access to all registered tools and agent capabilities.

Details

oauth.py:364 (source) -> oauth.py:374 (loop miss) -> oauth.py:381 (sink)
python
# source
 def validate token(self, token: str) -> bool:
  for stored token in self. tokens.values():
    if stored token.access token == token:
      return not stored token.is expired()
 
# sink -- tokens is empty by default, loop never executes, falls through
  return True

PoC

bash
# install: pip install -e src/praisonai
 # start server: praisonai mcp serve --transport http-stream --port 8080

curl -s -X POST http://127.0.0.1:8080/mcp 
 -H "Authorization: Bearer fake token abc123" 
 -H "Content-Type: application/json" 
 -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

# expected output: 200 OK with full tool list (50+ tools)
# including praisonai.agent.run, praisonai.workflow.run, praisonai.containers.file write

Impact

Any unauthenticated attacker with network access to the MCP HTTP server can call all registered tools including agent execution, workflow runs, container file read/write, and skill loading. The server binds to 0.0.0.0 by default with no API key required.

Suggested Fix

python
def validate token(self, token: str) -> bool:
  for stored token in self. tokens.values():
    if stored token.access token == token:
      return not stored token.is expired()
  # Unknown tokens must be rejected.
  # For external/JWT tokens, call the introspection endpoint here before returning.
  return False

Fix

Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

PYSEC-2026-468

Affected Products

Praisonai