CVE-2026-47396
published 2026-05-29CVE-2026-47396: PraisonAI call server exposes unauthenticated agent listing, invocation, and deletion when CALL_SERVER_TOKEN is unset ### Summary PraisonAI's call server…
critical
PraisonAI call server exposes unauthenticated agent listing, invocation, and deletion when CALL_SERVER_TOKEN is unset
### Summary
PraisonAI's call server exposes a network-facing agent control API without authentication when `CALL_SERVER_TOKEN` is not configured.
The affected component is the `praisonai.api.agent_invoke` router as mounted by `praisonai.api.call`. The authentication helper `verify_token()` fails open when `CALL_SERVER_TOKEN` is unset. Since every sensitive agent-control endpoint depends on this helper, starting the call server without a token allows any reachable client to list agents, inspect agent metadata and instructions, invoke agents, and unregister agents.
This is security-relevant because the bundled call server includes the vulnerable router and binds to `0.0.0.0`. As a result, operators who launch the call server without explicitly setting `CALL_SERVER_TOKEN` may unintentionally expose an unauthenticated remote agent control plane.
### Details
The vulnerable behavior is caused by a fail-open authentication default.
In `praisonai/api/agent_invoke.py`, `CALL_SERVER_TOKEN` is read from the environment:
```python
CALL_SERVER_TOKEN = os.getenv('CALL_SERVER_TOKEN')
```
The authentication dependency then returns successfully when the token is not configured:
```python
async def verify_token(request: Request, authorization: Optional[str] = Header(None)) -> None:
if not FASTAPI_AVAILABLE or not CALL_SERVER_TOKEN:
return # No authentication if FastAPI unavailable or no token set
```
This means that the absence of `CALL_SERVER_TOKEN` disables authentication entirely.
The same helper is used by sensitive agent-control routes, including:
```python
@router.post("/agents/{agent_id}/invoke")
async def invoke_agent(..., _: None = Depends(verify_token))
@router.get("/agents")
async def list_agents(_: None = Depends(verify_token))
@router.delete("/agents/{agent_id}")
async def unregister_agent_endpoint(agent_id: str, _: None = Depends(verify_toAffected
1 ranges
| Vendor | Product | Version range | Fixed in |
|---|---|---|---|
| mervinpraison | praisonai | >= 0 < 4.6.40 | 4.6.40 |
Stop checking back — get the weekly exploitation signal.
Every Monday: what got weaponized or added to CISA KEV in the last seven days — each CVE cross-linked to its PoC, Nuclei template, and detection rule. Free, one email a week, unsubscribe in one click.
No detection rules found.
No public exploits indexed.
No writeups or analysis indexed.
2026-05-29
Published