CVE-2026-55541
PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforced
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but _create_agents_app() and _create_unified_app() 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.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.8
PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforced
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but _create_agents_app() and _create_unified_app() 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.
- Record
CVE-2026-55541- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-862
- Updated
- 2026-11-02
EUVDEUVD-2026-65517
8.8
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but _create_agents_app() and _create_unified_app() 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.
- Record
EUVD-2026-65517- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-pvxx-r596-f5qj
8.8
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 _create_agents_app(config). But that function never reads config["api_key"]. The FastAPI app gets created with no auth at all. Same thing in _create_unified_app.
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 "api_key" src/praisonai/praisonai/cli/features/serve.py
107: --api-key <key> API key for authentication
199: "api_key": {"default": None},
847: "api_key": {"default": None},
Endpoints exposed without auth
POST /agents— runs the full agent workflowPOST /agents/{name}— invokes a specific agentPOST /api/v1/agents/{id}/invoke— n8n integration endpointGET /— lists all endpointsGET /__praisonai__/discovery— service discovery
Not the same as CVE-2026-44338
CVE-2026-44338 was about the legacy deploy/api.py hardcoding AUTH_ENABLED = 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
python3 -m venv /tmp/poc-venv
/tmp/poc-venv/bin/pip install praisonai==4.6.50 fastapi starlette httpx pyyaml
Script
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.agent_invoke",
"praisonai.agents_generator", "praisonai.inc"]:
sys.modules[m] = types.ModuleType(m)
disc = sys.modules["praisonai.endpoints.discovery"]
class Fake:
def __init__(self, **k): pass
def add_provider(self, *a, **k): pass
def add_endpoint(self, *a, **k): pass
def to_dict(self): return {}
disc.create_discovery_document = lambda **k: Fake()
disc.EndpointInfo = Fake
disc.ProviderInfo = Fake
sys.modules["praisonai.endpoints.server"].add_discovery_routes = lambda a,b: None
sys.modules["praisonai.api.agent_invoke"].FASTAPI_AVAILABLE = False
class FakeGen:
def __init__(self, **k): pass
def generate_crew_and_kickoff(self):
return {"executed": True, "result": "workflow ran"}
sys.modules["praisonai.agents_generator"].AgentsGenerator = FakeGen
class FakeLLM:
def to_dict(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()._create_agents_app({
"file": f.name, "host": "0.0.0.0", "port": 8000,
"path": "/agents", "reload": False,
"api_key": "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 TOTALLY_WRONG"})
print(f"No auth header → {r1.status_code}") # 200
print(f"Wrong key → {r2.status_code}") # 200
os.unlink(f.name)
Output
No auth header → 200
Wrong key → 200
Both succeed. The key is ignored.
Live server test
# start server with --api-key
praisonai serve agents --api-key supersecret --host 0.0.0.0…
- Record
GHSA-pvxx-r596-f5qj- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-862
- Updated
- 2026-11-02
NVD
8.8
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but _create_agents_app() and _create_unified_app() 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.
- Record
CVE-2026-55541- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-862
- Updated
- 2026-11-02
OSV
8.8
PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforced
PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.58, praisonai serve agents and praisonai serve unified parse --api-key but _create_agents_app() and _create_unified_app() 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.
- Record
CVE-2026-55541- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVGHSA-pvxx-r596-f5qj
8.8
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 _create_agents_app(config). But that function never reads config["api_key"]. The FastAPI app gets created with no auth at all. Same thing in _create_unified_app.
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 "api_key" src/praisonai/praisonai/cli/features/serve.py
107: --api-key <key> API key for authentication
199: "api_key": {"default": None},
847: "api_key": {"default": None},
Endpoints exposed without auth
POST /agents— runs the full agent workflowPOST /agents/{name}— invokes a specific agentPOST /api/v1/agents/{id}/invoke— n8n integration endpointGET /— lists all endpointsGET /__praisonai__/discovery— service discovery
Not the same as CVE-2026-44338
CVE-2026-44338 was about the legacy deploy/api.py hardcoding AUTH_ENABLED = 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
python3 -m venv /tmp/poc-venv
/tmp/poc-venv/bin/pip install praisonai==4.6.50 fastapi starlette httpx pyyaml
Script
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.agent_invoke",
"praisonai.agents_generator", "praisonai.inc"]:
sys.modules[m] = types.ModuleType(m)
disc = sys.modules["praisonai.endpoints.discovery"]
class Fake:
def __init__(self, **k): pass
def add_provider(self, *a, **k): pass
def add_endpoint(self, *a, **k): pass
def to_dict(self): return {}
disc.create_discovery_document = lambda **k: Fake()
disc.EndpointInfo = Fake
disc.ProviderInfo = Fake
sys.modules["praisonai.endpoints.server"].add_discovery_routes = lambda a,b: None
sys.modules["praisonai.api.agent_invoke"].FASTAPI_AVAILABLE = False
class FakeGen:
def __init__(self, **k): pass
def generate_crew_and_kickoff(self):
return {"executed": True, "result": "workflow ran"}
sys.modules["praisonai.agents_generator"].AgentsGenerator = FakeGen
class FakeLLM:
def to_dict(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()._create_agents_app({
"file": f.name, "host": "0.0.0.0", "port": 8000,
"path": "/agents", "reload": False,
"api_key": "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 TOTALLY_WRONG"})
print(f"No auth header → {r1.status_code}") # 200
print(f"Wrong key → {r2.status_code}") # 200
os.unlink(f.name)
Output
No auth header → 200
Wrong key → 200
Both succeed. The key is ignored.
Live server test
# start server with --api-key
praisonai serve agents --api-key supersecret --host 0.0.0.0…
- Record
GHSA-pvxx-r596-f5qj- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-862
- Updated
- 2026-11-02
OSVPYSEC-2026-3893
8.8
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 _create_agents_app(config). But that function never reads config["api_key"]. The FastAPI app gets created with no auth at all. Same thing in _create_unified_app.
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 "api_key" src/praisonai/praisonai/cli/features/serve.py
107: --api-key <key> API key for authentication
199: "api_key": {"default": None},
847: "api_key": {"default": None},
Endpoints exposed without auth
POST /agents— runs the full agent workflowPOST /agents/{name}— invokes a specific agentPOST /api/v1/agents/{id}/invoke— n8n integration endpointGET /— lists all endpointsGET /__praisonai__/discovery— service discovery
Not the same as CVE-2026-44338
CVE-2026-44338 was about the legacy deploy/api.py hardcoding AUTH_ENABLED = 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
python3 -m venv /tmp/poc-venv
/tmp/poc-venv/bin/pip install praisonai==4.6.50 fastapi starlette httpx pyyaml
Script
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.agent_invoke",
"praisonai.agents_generator", "praisonai.inc"]:
sys.modules[m] = types.ModuleType(m)
disc = sys.modules["praisonai.endpoints.discovery"]
class Fake:
def __init__(self, **k): pass
def add_provider(self, *a, **k): pass
def add_endpoint(self, *a, **k): pass
def to_dict(self): return {}
disc.create_discovery_document = lambda **k: Fake()
disc.EndpointInfo = Fake
disc.ProviderInfo = Fake
sys.modules["praisonai.endpoints.server"].add_discovery_routes = lambda a,b: None
sys.modules["praisonai.api.agent_invoke"].FASTAPI_AVAILABLE = False
class FakeGen:
def __init__(self, **k): pass
def generate_crew_and_kickoff(self):
return {"executed": True, "result": "workflow ran"}
sys.modules["praisonai.agents_generator"].AgentsGenerator = FakeGen
class FakeLLM:
def to_dict(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()._create_agents_app({
"file": f.name, "host": "0.0.0.0", "port": 8000,
"path": "/agents", "reload": False,
"api_key": "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 TOTALLY_WRONG"})
print(f"No auth header → {r1.status_code}") # 200
print(f"Wrong key → {r2.status_code}") # 200
os.unlink(f.name)
Output
No auth header → 200
Wrong key → 200
Both succeed. The key is ignored.
Live server test
# start server with --api-key
praisonai serve agents --api-key supersecret --host 0.0.0.0…
- Record
PYSEC-2026-3893- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
praisonaiPyPI |
before 4.6.58 | 4.6.58 |
praisonaiPyPI |
before 4.6.58, plus listed versions 0.0.10.0.100.0.110.0.120.0.13 Show 45 moreShow less0.0.140.0.150.0.160.0.170.0.180.0.190.0.20.0.200.0.210.0.220.0.230.0.240.0.250.0.260.0.270.0.280.0.290.0.30.0.300.0.310.0.320.0.330.0.340.0.350.0.360.0.370.0.380.0.390.0.40.0.400.0.410.0.420.0.430.0.440.0.450.0.460.0.470.0.480.0.490.0.50.0.500.0.520.0.530.0.540.0.55 |
4.6.58 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-55541 is a high vulnerability (CVSS 8.8) in Mervinpraison Praisonai, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in praisonai 4.6.58.
References
github.com/MervinPraison/PraisonAI/security/advisories/GHSA-pvxx-r596-f5qj
github.com/MervinPraison/PraisonAI/commit/2f9677abb2ea68eab864ee8b6a828fd0141612e1
github.com/MervinPraison/PraisonAI/releases/tag/v4.6.58
github.com/advisories/GHSA-pvxx-r596-f5qj
github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55541.json
nvd.nist.gov/vuln/detail/CVE-2026-55541
github.com/MervinPraison/PraisonAI
pypi.org/project/praisonai
Left out here: 698 versions and the rest of 3 source descriptions. The JSON record has them.