CVE-2026-44338: PraisonAI: unauthenticated API triggers agent workflows
GHSA-6rmh-7xcm-cpxj HIGH NUCLEI TEMPLATE CISA: TRACK*PraisonAI's legacy Flask API server ships with authentication hardcoded off — AUTH_ENABLED=False, binding to 0.0.0.0:8080 — meaning any network-reachable caller can enumerate configured agents via GET /agents and trigger the full agents.yaml workflow via POST /chat with zero credentials. The blast radius depends entirely on what the operator's agents.yaml is configured to do: at minimum unauthenticated LLM quota drain; at worst, invocation of any privileged tool calls (file ops, web requests, database queries) the workflow is permitted. Exploitation is trivially simple — a single unauthenticated HTTP POST suffices — and with 40 prior CVEs in the same package and EPSS in the 83rd percentile, this package warrants elevated scrutiny. Patch to praisonai 4.6.34 immediately, or as a stopgap block external access to port 8080 and migrate to the newer `serve agents` command which defaults to 127.0.0.1 with --api-key support.
What is the risk?
HIGH for any PraisonAI deployment running the legacy api_server.py entrypoint with network exposure. The insecure-by-default configuration (hardcoded AUTH_ENABLED=False, 0.0.0.0 bind) means any deployment that did not explicitly add firewall rules is likely vulnerable. No credentials, no AI/ML knowledge, and no prior reconnaissance beyond port scanning are required to exploit. Risk compounds with the capability surface of the configured agents.yaml — environments where the agent has write access to filesystems, databases, or external APIs face material impact beyond quota drain. The patched version 4.6.34 is available, making this primarily a patch-velocity and detection risk.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| PraisonAI | pip | >= 2.5.6, <= 4.6.33 | 4.6.34 |
Do you use PraisonAI? You're affected.
How severe is it?
What is the attack surface?
What should I do?
6 steps-
Patch: upgrade praisonai to >= 4.6.34 which corrects the authentication default.
-
Immediate workaround if patching is delayed: apply firewall/security-group rules blocking all external inbound access to port 8080 on PraisonAI hosts.
-
Migrate from legacy api_server.py to the newer
serve agentscommand (binds to 127.0.0.1, supports --api-key). -
Audit deployed agents.yaml files to assess blast radius — focus on tool definitions with write, delete, or execute capabilities.
-
Review LLM provider API usage logs for anomalous spikes indicating unauthorized workflow invocations since the deployment date.
-
Detection: monitor application logs for 200 responses to GET /agents or POST /chat requests lacking an Authorization header — any such response is a confirmed exploitation event.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-44338?
PraisonAI's legacy Flask API server ships with authentication hardcoded off — AUTH_ENABLED=False, binding to 0.0.0.0:8080 — meaning any network-reachable caller can enumerate configured agents via GET /agents and trigger the full agents.yaml workflow via POST /chat with zero credentials. The blast radius depends entirely on what the operator's agents.yaml is configured to do: at minimum unauthenticated LLM quota drain; at worst, invocation of any privileged tool calls (file ops, web requests, database queries) the workflow is permitted. Exploitation is trivially simple — a single unauthenticated HTTP POST suffices — and with 40 prior CVEs in the same package and EPSS in the 83rd percentile, this package warrants elevated scrutiny. Patch to praisonai 4.6.34 immediately, or as a stopgap block external access to port 8080 and migrate to the newer `serve agents` command which defaults to 127.0.0.1 with --api-key support.
Is CVE-2026-44338 actively exploited?
No confirmed active exploitation of CVE-2026-44338 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-44338?
1. Patch: upgrade praisonai to >= 4.6.34 which corrects the authentication default. 2. Immediate workaround if patching is delayed: apply firewall/security-group rules blocking all external inbound access to port 8080 on PraisonAI hosts. 3. Migrate from legacy api_server.py to the newer `serve agents` command (binds to 127.0.0.1, supports --api-key). 4. Audit deployed agents.yaml files to assess blast radius — focus on tool definitions with write, delete, or execute capabilities. 5. Review LLM provider API usage logs for anomalous spikes indicating unauthorized workflow invocations since the deployment date. 6. Detection: monitor application logs for 200 responses to GET /agents or POST /chat requests lacking an Authorization header — any such response is a confirmed exploitation event.
What systems are affected by CVE-2026-44338?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, agentic AI deployments, model serving, AI API endpoints.
What is the CVSS score for CVE-2026-44338?
CVE-2026-44338 has a CVSS v3.1 base score of 7.3 (HIGH). The EPSS exploitation probability is 26.80%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0002.002 AI Agent Configuration AML.T0006 Active Scanning AML.T0034.002 Agentic Resource Consumption AML.T0049 Exploit Public-Facing Application AML.T0053 AI Agent Tool Invocation AML.T0084 Discover AI Agent Configuration AML.T0084.001 Tool Definitions Compliance Controls Affected
What are the technical details?
Original Advisory
### Summary PraisonAI ships a legacy Flask API server with authentication disabled by default. When that server is used, any caller that can reach it can access `/agents` and trigger the configured `agents.yaml` workflow through `/chat` without providing a token. ### Details The vulnerable server is the shipped `src/praisonai/api_server.py` entrypoint. - `AUTH_ENABLED = False` and `AUTH_TOKEN = None` are hard-coded at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:15)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:15). - `check_auth()` returns `True` whenever authentication is disabled, so both protected routes fail open by design at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:18)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:18). - `POST /chat` only checks that the request JSON contains a `message` key and then runs `PraisonAI(agent_file="agents.yaml").run()` at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:31)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:31). - `GET /agents` is guarded by the same no-op authentication check and returns agent metadata at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:55)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:66):55). - When launched directly, the same script binds to `0.0.0.0:8080` at [src/praisonai/api_server.py](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:66). The deploy subsystem keeps the same insecure authentication default: - `APIConfig` defaults `auth_enabled` to `False` in [[src/praisonai/praisonai/deploy/models.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/models.py:23)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/models.py:23). - The generated sample API deployment YAML recommends `host: 0.0.0.0` together with `auth_enabled: false` in [[src/praisonai/praisonai/deploy/schema.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/schema.py:108)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/schema.py:108). For scope clarity: the newer `serve agents` command is safer by default, because it binds to `127.0.0.1` and supports `--api-key` in [[src/praisonai/praisonai/cli/commands/serve.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/cli/commands/serve.py:155)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/cli/commands/serve.py:155). This report is about the shipped legacy API server and the generated/sample API deployment path above. Version scope: - `v2.5.6` already ships the same `src/praisonai/api_server.py` implementation. - The current PyPI release on May 1, 2026 is `4.6.33`, and it still ships the same unauthenticated server logic. ### PoC The following route-level reproduction was verified locally and proves that the shipped `api_server.py` exposes `/agents` and `/chat` without authentication. 1. From the repository root, create a throwaway environment with the server's direct Flask dependencies: ```bash python3 -m venv /tmp/praisonai-ghsa-venv /tmp/praisonai-ghsa-venv/bin/pip install flask flask-cors ``` 2. Execute the shipped `src/praisonai/api_server.py` under a minimal stub for `praisonai.PraisonAI` so only the server auth logic is exercised: ```bash /tmp/praisonai-ghsa-venv/bin/python - <<'PY' import importlib.util import pathlib import sys import types stub = types.ModuleType("praisonai") class DummyPraisonAI: def __init__(self, agent_file="agents.yaml"): self.agent_file = agent_file def run(self): return {"ran": True, "agent_file": self.agent_file} stub.PraisonAI = DummyPraisonAI sys.modules["praisonai"] = stub path = pathlib.Path("src/praisonai/api_server.py").resolve() spec = importlib.util.spec_from_file_location("api_server_local", path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) client = mod.app.test_client() print(client.get("/agents").status_code, client.get("/agents").get_data(as_text=True)) print(client.post("/chat", json={"message": "hello"}).status_code, client.post("/chat", json={"message": "hello"}).get_data(as_text=True)) PY ``` 3. Observed result: ```text 200 {"agent_file":"agents.yaml","agents":["default"]} 200 {"response":{"agent_file":"agents.yaml","ran":true},"status":"success"} ``` Both endpoints succeed without any `Authorization` header. ### Impact Any reachable caller can invoke the legacy API server's protected functionality without a token. At minimum, this allows: - unauthenticated enumeration of the configured agent file through `/agents` - unauthenticated triggering of the locally configured `agents.yaml` workflow through `/chat` - repeated consumption of model/API quota and any other side effects performed by that workflow - exposure of whatever result `PraisonAI.run()` returns to the unauthenticated caller This is not the same as arbitrary prompt injection by itself, because the current `/chat` handler ignores the submitted `message` value and simply runs the configured workflow. The impact therefore depends on what the operator's `agents.yaml` is allowed to do, but the authentication bypass is unconditional in the shipped legacy server.
Exploitation Scenario
An attacker running an internet-wide scan on port 8080 identifies a cloud-deployed PraisonAI instance. They send a curl GET /agents with no Authorization header and receive JSON containing the agents.yaml path and configured agent names — zero resistance. They then issue repeated POST /chat requests with a minimal JSON body ({"message": "run"}) to invoke the configured workflow in a loop. If the agents.yaml includes tool definitions for web browsing, file access, or code execution, the attacker gains those capabilities through the agent. At minimum, they drain the operator's OpenAI or Anthropic API quota to zero and receive the workflow output in plaintext responses — all without a single credential.
Weaknesses (CWE)
CWE-1188 Initialization of a Resource with an Insecure Default
Primary
CWE-306 Missing Authentication for Critical Function
Primary
CWE-668 Exposure of Resource to Wrong Sphere
Primary
CWE-1188 — Initialization of a Resource with an Insecure Default: The product initializes or sets a resource with a default that is intended to be changed by the product's installer, administrator, or maintainer, but the default is not secure.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L References
Timeline
Scanner Template Available
A Nuclei vulnerability scanner template exists for this CVE. You can scan your infrastructure for this vulnerability immediately.
View template on GitHubnuclei -t http/cves/2026/cve-2026-44338.yaml -u https://target.example.com Related Vulnerabilities
GHSA-vmmj-pfw7-fjwp 9.9 praisonai: sandbox escape gives RCE via codeMode tool
Same package: praisonai CVE-2026-47392 9.9 praisonaiagents: RCE via Python sandbox bypass
Same package: praisonai GHSA-vc46-vw85-3wvm 9.8 PraisonAI: RCE via malicious workflow YAML execution
Same package: praisonai GHSA-9qhq-v63v-fv3j 9.8 PraisonAI: RCE via MCP command injection
Same package: praisonai CVE-2026-39890 9.8 PraisonAI: YAML deserialization enables unauthenticated RCE
Same package: praisonai