CVE-2026-55541: PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforced
Summary
praisonai serve agents and praisonai serve unified both accept --api-key for authentication. The flag is parsed but never wired into the FastAPI app — no middleware, no header check, nothing. The server runs wide open regardless of what key you set. Tested on 4.6.50 from PyPI.
Affected versions
- Confirmed on 4.6.50 (current PyPI, 2026-06-02) - Likely since 4.6.34 when the serve subsystem shipped - File: src/praisonai/praisonai/cli/features/serve.py
What happens
The CLI defines --api-key in the arg spec (serve.py:199) and passes the parsed value into createagentsapp(config). But that function never reads config["apikey"]. The FastAPI app gets created with no auth at all. Same thing in createunifiedapp.
The help text says --api-key <key> API key for authentication, so this isn't ambiguous — it's supposed to protect the server. It just doesn't. $ grep -n "apikey" src/praisonai/praisonai/cli/features/serve.py 107: --api-key <key> API key for authentication 199: "apikey": {"default": None}, 847: "apikey": {"default": None},
Endpoints exposed without auth
- POST /agents — runs the full agent workflow - POST /agents/{name} — invokes a specific agent - POST /api/v1/agents/{id}/invoke — n8n integration endpoint - GET / — lists all endpoints - GET /praisonai/discovery — service discovery
Not the same as CVE-2026-44338
CVE-2026-44338 was about the legacy deploy/api.py hardcoding AUTHENABLED = False. That was fixed in 4.6.34. This bug is in the newer serve subsystem that shipped in the same release — the --api-key flag exists but was never connected to anything.
PoC
Setup
bash python3 -m venv /tmp/poc-venv /tmp/poc-venv/bin/pip install praisonai==4.6.50 fastapi starlette httpx pyyaml
Script
python import sys, types, tempfile, os
Stub heavy deps so we only test the serve auth logic for m in ["praisonai.endpoints.discovery", "praisonai.endpoints.server", "praisonai.api", "praisonai.api.agentinvoke", "praisonai.agentsgenerator", "praisonai.inc"]: sys.modules[m] = types.ModuleType(m)
disc = sys.modules["praisonai.endpoints.discovery"] class Fake: def init(self, k): pass def addprovider(self, a, k): pass def addendpoint(self, a, k): pass def todict(self): return {} disc.creatediscoverydocument = lambda k: Fake() disc.EndpointInfo = Fake disc.ProviderInfo = Fake sys.modules["praisonai.endpoints.server"].adddiscoveryroutes = lambda a,b: None sys.modules["praisonai.api.agentinvoke"].FASTAPIAVAILABLE = False
class FakeGen: def init(self, k): pass def generatecrewandkickoff(self): return {"executed": True, "result": "workflow ran"} sys.modules["praisonai.agentsgenerator"].AgentsGenerator = FakeGen
class FakeLLM: def todict(self): return {} sys.modules["praisonai.inc"].LLMConfig = FakeLLM
f = tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) f.write("name: T\nagents:\n a:\n name: A\n role: R\n goal: G\n backstory: B\n") f.flush()
from praisonai.cli.features.serve import ServeHandler app = ServeHandler().createagentsapp({ "file": f.name, "host": "0.0.0.0", "port": 8000, "path": "/agents", "reload": False, "apikey": "supersecret", # <-- should protect the server })
from starlette.testclient import TestClient c = TestClient(app)
r1 = c.post("/agents", json={"query": "run"}) r2 = c.post("/agents", json={"query": "run"}, headers={"Authorization": "Bearer TOTALLYWRONG"})
print(f"No auth header → {r1.statuscode}") # 200 print(f"Wrong key → {r2.statuscode}") # 200
os.unlink(f.name)
Output
No auth header → 200 Wrong key → 200
Both succeed. The key is ignored.
Live server test
bash start server with --api-key praisonai serve agents --api-key supersecret --host 0.0.0.0 --port 9999
hit it without any auth curl -s -X POST http://localhost:9999/agents \ -H "Content-Type: application/json" \ -d '{"query":"run all agents"}' → 200, workflow executes
Impact
Anyone who can reach the server can trigger agent workflows without credentials. The operator set --api-key and got no error, so they think it's protected.
What an attacker gets depends on what the agents.yaml workflow can do — LLM calls, tool use, file access, code execution, web requests. At minimum it's unauthenticated API quota burn.
Fix
createagentsapp() and createunifiedapp() need to actually read config["apikey"] and add a FastAPI dependency that checks the Authorization: Bearer header. When binding to a non-loopback address without --api-key, the server should warn or refuse to start.
References
- CVE-2026-44338 / GHSA-6rmh-7xcm-cpxj (prior auth bypass, different component)
Other sources
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but createagentsapp() and createunifiedapp() do not install a credential check. Unauthenticated callers can reach POST /agents and POST /api/v1/agents/{id}/invoke. This issue is fixed in version 4.6.58.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/PraisonAIto a version that resolves this vulnerability.Fixed in 4.6.58 - Upgrade
Upgrade
praisonaito a version that resolves this vulnerability.Fixed in 4.6.58 - Configuration
Modify the FastAPI app wiring in _create_agents_app() and _create_unified_app() to actually read config["api_key"] and add a FastAPI dependency/middleware that validates the Authorization: Bearer header before allowing endpoints such as POST /agents and POST /api/v1/agents/{id}/invoke to execute workflows.
praisonai serve (FastAPI app created by _create_agents_app/_create_unified_app) Authorization header check against config["api_key"] = Require Authorization: Bearer <api_key> and reject requests without/with wrong key (no bearer -> 401/403 instead of allowing workflow execution)