Every CVE Search/ Get API key

CVE-2026-55538

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

7.3 HighFix available

PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.51, praisonai serve agents parses config["api_key"] but _create_agents_app() does not authenticate POST /agents or POST /agents/{agent_name}. Missing or incorrect bearer and X-API-Key values still reach agent execution. This issue is fixed in version 4.6.58.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
Low

Exploit likelihood

0.45%Up 0.2 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.3

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.51, praisonai serve agents parses config["api_key"] but _create_agents_app() does not authenticate POST /agents or POST /agents/{agent_name}. Missing or incorrect bearer and X-API-Key values still reach agent execution. This issue is fixed in version 4.6.58.

Record
CVE-2026-55538
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weakness
CWE-306
Updated
2026-11-02
EUVDEUVD-2026-65514 7.3

PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.51, praisonai serve agents parses config["api_key"] but _create_agents_app() does not authenticate POST /agents or POST /agents/{agent_name}. Missing or incorrect bearer and X-API-Key values still reach agent execution. This issue is fixed in version 4.6.58.

Record
EUVD-2026-65514
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Updated
2026-11-02
GitHub AdvisoriesGHSA-r7v3-x45f-g7hp 7.3

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

Summary

praisonai serve agents exposes HTTP routes that invoke registered agents. The CLI advertises --api-key with help text "API key for authentication", parses it, and forwards it into ServeHandler. But _create_agents_app() never reads config["api_key"] again and installs no auth dependency or middleware on its direct routes. The configured key is a no-op flag.

As a result, an unauthenticated network caller can invoke exposed agents (POST /agents and POST /agents/{agent_name}) even when the operator passed --api-key. Requests with no credentials, a wrong Authorization: Bearer, a wrong X-API-Key, or an empty bearer all reach agent.start().

The failure is made sharper by the fact that a working auth dependency already exists in the same module — praisonai.api.agent_invoke.verify_token guards every /api/v1/... route with Depends(verify_token) and is mounted into the very same app. The direct n8n-compat routes simply do not use it.

Technical Detail

Source-to-sink trace

1. CLI advertises and forwards --api-key:

# cli/commands/serve.py
@app.command("agents")
def serve_agents(..., api_key: Optional[str] = typer.Option(None, "--api-key", help="API key for authentication")):
    ...
    if api_key:
        args.extend(["--api-key", api_key])
    exit_code = handle_serve_command(args)

2. cmd_agents() parses api_key into the spec — and that is the last time it is touched:

# cli/features/serve.py — cmd_agents()
spec = { ..., "api_key": {"default": None} }
parsed = self._parse_args(args, spec)
app = self._create_agents_app(parsed)

A grep of the entire cli/features/serve.py for api_key returns only the two spec entries (cmd_agents line ~199 and cmd_unified line ~847). config["api_key"] is never read inside _create_agents_app() / _create_unified_app(); it is never compared, and no dependency is attached.

3. _create_agents_app() imports FastAPI, HTTPException, Request — no Depends, no Header, no auth middleware. Every HTTPException raised in the agents routes is 400/404/500 (validation / not-found / execution error); none is 401.

4. Sink — unauthenticated request reaches agent.start():

# cli/features/serve.py
@app.post("/agents/{agent_name}")          # n8n compatibility route
async def invoke_single_agent(agent_name: str, request: Request):
    body = await request.json()
    query = body.get("query", "") or body.get("message", "")
    ...
    agent = agent_invoke.get_agent(agent_name)
    result = await loop.run_in_executor(None, agent.start, query)   # no auth anywhere above
    return {"response": str(result)}
 
@app.post(path)                            # default path "/agents"
async def invoke_agents(request: Request, query_data: AgentQuery = None):
    ... agent.start(query) ...

The auth dependency exists — it just isn't applied here

_create_agents_app() mounts the agent_invoke router into the same app:

# cli/features/serve.py
if getattr(agent_invoke, 'FASTAPI_AVAILABLE', False) and hasattr(agent_invoke, 'router'):
    app.include_router(agent_invoke.router)

That router properly authenticates every sensitive route:

# api/agent_invoke.py
CALL_SERVER_TOKEN = os.getenv('CALL_SERVER_TOKEN')
async def verify_token(request, authorization=Header(None)) -> None:
    ...
    if token != CALL_SERVER_TOKEN:
        raise HTTPException(status_code=401, detail="Unauthorized")
 
@router.get("/api/v1/agents")
async def list_agents(_: None = Depends(verify_token)): ...   # and register/unregister/info all use it

So in the same process GET /api/v1/agents returns 401 without a token, while POST /agents/{agent_name} returns 200. Note also that verify_token reads the CALL_SERVER_TOKEN env var — not the CLI --api-key — so the CLI option feeds no auth path at all.

Trigger conditions

Record
GHSA-r7v3-x45f-g7hp
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weakness
CWE-306
Updated
2026-11-02
NVD 7.3

PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.51, praisonai serve agents parses config["api_key"] but _create_agents_app() does not authenticate POST /agents or POST /agents/{agent_name}. Missing or incorrect bearer and X-API-Key values still reach agent execution. This issue is fixed in version 4.6.58.

Record
CVE-2026-55538
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weakness
CWE-306
Updated
2026-11-02
OSV 7.3

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

PraisonAI is a multi-agent teams system. Prior to praisonai 4.6.51, praisonai serve agents parses config["api_key"] but _create_agents_app() does not authenticate POST /agents or POST /agents/{agent_name}. Missing or incorrect bearer and X-API-Key values still reach agent execution. This issue is fixed in version 4.6.58.

Record
CVE-2026-55538
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weakness
CWE-306
Updated
2026-11-02
OSVGHSA-r7v3-x45f-g7hp 7.3

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

Summary

praisonai serve agents exposes HTTP routes that invoke registered agents. The CLI advertises --api-key with help text "API key for authentication", parses it, and forwards it into ServeHandler. But _create_agents_app() never reads config["api_key"] again and installs no auth dependency or middleware on its direct routes. The configured key is a no-op flag.

As a result, an unauthenticated network caller can invoke exposed agents (POST /agents and POST /agents/{agent_name}) even when the operator passed --api-key. Requests with no credentials, a wrong Authorization: Bearer, a wrong X-API-Key, or an empty bearer all reach agent.start().

The failure is made sharper by the fact that a working auth dependency already exists in the same module — praisonai.api.agent_invoke.verify_token guards every /api/v1/... route with Depends(verify_token) and is mounted into the very same app. The direct n8n-compat routes simply do not use it.

Technical Detail

Source-to-sink trace

1. CLI advertises and forwards --api-key:

# cli/commands/serve.py
@app.command("agents")
def serve_agents(..., api_key: Optional[str] = typer.Option(None, "--api-key", help="API key for authentication")):
    ...
    if api_key:
        args.extend(["--api-key", api_key])
    exit_code = handle_serve_command(args)

2. cmd_agents() parses api_key into the spec — and that is the last time it is touched:

# cli/features/serve.py — cmd_agents()
spec = { ..., "api_key": {"default": None} }
parsed = self._parse_args(args, spec)
app = self._create_agents_app(parsed)

A grep of the entire cli/features/serve.py for api_key returns only the two spec entries (cmd_agents line ~199 and cmd_unified line ~847). config["api_key"] is never read inside _create_agents_app() / _create_unified_app(); it is never compared, and no dependency is attached.

3. _create_agents_app() imports FastAPI, HTTPException, Request — no Depends, no Header, no auth middleware. Every HTTPException raised in the agents routes is 400/404/500 (validation / not-found / execution error); none is 401.

4. Sink — unauthenticated request reaches agent.start():

# cli/features/serve.py
@app.post("/agents/{agent_name}")          # n8n compatibility route
async def invoke_single_agent(agent_name: str, request: Request):
    body = await request.json()
    query = body.get("query", "") or body.get("message", "")
    ...
    agent = agent_invoke.get_agent(agent_name)
    result = await loop.run_in_executor(None, agent.start, query)   # no auth anywhere above
    return {"response": str(result)}
 
@app.post(path)                            # default path "/agents"
async def invoke_agents(request: Request, query_data: AgentQuery = None):
    ... agent.start(query) ...

The auth dependency exists — it just isn't applied here

_create_agents_app() mounts the agent_invoke router into the same app:

# cli/features/serve.py
if getattr(agent_invoke, 'FASTAPI_AVAILABLE', False) and hasattr(agent_invoke, 'router'):
    app.include_router(agent_invoke.router)

That router properly authenticates every sensitive route:

# api/agent_invoke.py
CALL_SERVER_TOKEN = os.getenv('CALL_SERVER_TOKEN')
async def verify_token(request, authorization=Header(None)) -> None:
    ...
    if token != CALL_SERVER_TOKEN:
        raise HTTPException(status_code=401, detail="Unauthorized")
 
@router.get("/api/v1/agents")
async def list_agents(_: None = Depends(verify_token)): ...   # and register/unregister/info all use it

So in the same process GET /api/v1/agents returns 401 without a token, while POST /agents/{agent_name} returns 200. Note also that verify_token reads the CALL_SERVER_TOKEN env var — not the CLI --api-key — so the CLI option feeds no auth path at all.

Trigger conditions

Record
GHSA-r7v3-x45f-g7hp
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Weakness
CWE-306
Updated
2026-11-02
OSVPYSEC-2026-3894 7.3

PraisonAI: [Auth Bypass] `praisonai serve agents --api-key` is silently ignored — agent-invocation routes (`POST /agents`, `POST /agents/{agent_name}`) run unauthenticated

Summary

praisonai serve agents exposes HTTP routes that invoke registered agents. The CLI advertises --api-key with help text "API key for authentication", parses it, and forwards it into ServeHandler. But _create_agents_app() never reads config["api_key"] again and installs no auth dependency or middleware on its direct routes. The configured key is a no-op flag.

As a result, an unauthenticated network caller can invoke exposed agents (POST /agents and POST /agents/{agent_name}) even when the operator passed --api-key. Requests with no credentials, a wrong Authorization: Bearer, a wrong X-API-Key, or an empty bearer all reach agent.start().

The failure is made sharper by the fact that a working auth dependency already exists in the same module — praisonai.api.agent_invoke.verify_token guards every /api/v1/... route with Depends(verify_token) and is mounted into the very same app. The direct n8n-compat routes simply do not use it.

Technical Detail

Source-to-sink trace

1. CLI advertises and forwards --api-key:

# cli/commands/serve.py
@app.command("agents")
def serve_agents(..., api_key: Optional[str] = typer.Option(None, "--api-key", help="API key for authentication")):
    ...
    if api_key:
        args.extend(["--api-key", api_key])
    exit_code = handle_serve_command(args)

2. cmd_agents() parses api_key into the spec — and that is the last time it is touched:

# cli/features/serve.py — cmd_agents()
spec = { ..., "api_key": {"default": None} }
parsed = self._parse_args(args, spec)
app = self._create_agents_app(parsed)

A grep of the entire cli/features/serve.py for api_key returns only the two spec entries (cmd_agents line ~199 and cmd_unified line ~847). config["api_key"] is never read inside _create_agents_app() / _create_unified_app(); it is never compared, and no dependency is attached.

3. _create_agents_app() imports FastAPI, HTTPException, Request — no Depends, no Header, no auth middleware. Every HTTPException raised in the agents routes is 400/404/500 (validation / not-found / execution error); none is 401.

4. Sink — unauthenticated request reaches agent.start():

# cli/features/serve.py
@app.post("/agents/{agent_name}")          # n8n compatibility route
async def invoke_single_agent(agent_name: str, request: Request):
    body = await request.json()
    query = body.get("query", "") or body.get("message", "")
    ...
    agent = agent_invoke.get_agent(agent_name)
    result = await loop.run_in_executor(None, agent.start, query)   # no auth anywhere above
    return {"response": str(result)}
 
@app.post(path)                            # default path "/agents"
async def invoke_agents(request: Request, query_data: AgentQuery = None):
    ... agent.start(query) ...

The auth dependency exists — it just isn't applied here

_create_agents_app() mounts the agent_invoke router into the same app:

# cli/features/serve.py
if getattr(agent_invoke, 'FASTAPI_AVAILABLE', False) and hasattr(agent_invoke, 'router'):
    app.include_router(agent_invoke.router)

That router properly authenticates every sensitive route:

# api/agent_invoke.py
CALL_SERVER_TOKEN = os.getenv('CALL_SERVER_TOKEN')
async def verify_token(request, authorization=Header(None)) -> None:
    ...
    if token != CALL_SERVER_TOKEN:
        raise HTTPException(status_code=401, detail="Unauthorized")
 
@router.get("/api/v1/agents")
async def list_agents(_: None = Depends(verify_token)): ...   # and register/unregister/info all use it

So in the same process GET /api/v1/agents returns 401 without a token, while POST /agents/{agent_name} returns 200. Note also that verify_token reads the CALL_SERVER_TOKEN env var — not the CLI --api-key — so the CLI option feeds no auth path at all.

Trigger conditions

Record
PYSEC-2026-3894
CVSS 3.1
7.3 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
praisonai
PyPI
before 4.6.58
4.6.58
praisonai
PyPI
before 4.6.58, plus listed versions
0.0.10.0.100.0.110.0.120.0.13
Show 45 moreShow less
0.0.140.0.150.0.160.0.170.0.180.0.190.0.20.0.200.0.210.0.220.0.230.0.240.0.250.0.260.0.270.0.280.0.290.0.30.0.300.0.310.0.320.0.330.0.340.0.350.0.360.0.370.0.380.0.390.0.40.0.400.0.410.0.420.0.430.0.440.0.450.0.460.0.470.0.480.0.490.0.50.0.500.0.520.0.530.0.540.0.55
4.6.58

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55538 is a high vulnerability (CVSS 7.3) in Mervinpraison Praisonai, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.45%, the 39th percentile. Fixed in praisonai 4.6.58.

References

This page doesn't list everything

Left out here: 698 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open