Skip to content

AgentMail webhook lacks signature verification, allowing unauthenticated message injection and sender spoofing

High
MervinPraison published GHSA-qj9c-59p6-8cgx Jun 25, 2026

Package

pip praisonai (pip)

Affected versions

<= 4.6.77

Patched versions

>= 4.6.78

Description

Summary

PraisonAI's AgentMail bot, when run in webhook (or hybrid) mode, starts an aiohttp webhook server bound to 0.0.0.0 and processes inbound message.received events without verifying any signature/HMAC and without authentication. The sender address and message body are taken directly from the attacker-controlled request body, so any network peer can inject messages into the agent with a spoofed sender (bypassing sender allow/block lists) and have the agent process the content and reply to an attacker-chosen address. Sibling bots (linear.py, whatsapp.py) fail closed when no secret is configured; AgentMail omits the check entirely. Runtime-confirmed; severity Medium.

Details

Affected component

  • Package: praisonai 4.6.63. File: src/praisonai/praisonai/bots/agentmail.py (AgentMailBot, webhook/hybrid mode).

Vulnerable code / root cause

Path:
src/praisonai/praisonai/bots/agentmail.py

Function:
_start_webhook_mode / _handle_email_webhook / _handle_message

Snippet:

# _start_webhook_mode: binds all interfaces
self._webhook_site = web.TCPSite(self._webhook_runner, "0.0.0.0", self._webhook_port)

# _handle_email_webhook: no signature/HMAC check, no auth
body = await request.json()
if body.get("type") != "message.received":
    return web.Response(status=200, text="OK")
asyncio.create_task(self._process_webhook_payload(body))   # dispatch attacker body
return web.Response(status=200, text="OK")

# _handle_message: agent processes content, replies to attacker-controlled sender
response = await self._session.chat(self._agent, sender_id, body, ...)
await self.send_message(channel_id=sender_id, ...)

Issue: attacker-controlled input is the raw webhook JSON (from, extracted_text, subject). The guard that should exist is provider signature verification — there is none here (no svix/HMAC, no webhooks_require_verification() call). The sink is self._session.chat(self._agent, ...) (agent invocation) and send_message(channel_id=sender_id, ...) (reply to the spoofed sender). Sibling handlers src/praisonai/praisonai/bots/linear.py and bots/whatsapp.py call webhooks_require_verification() and reject when no secret is set — AgentMail does not, so it fails open.

Attack flow

  1. Operator runs the AgentMail bot in webhook/hybrid mode (documented; binds 0.0.0.0, default path /webhook, default port 8080).
  2. Attacker POSTs a crafted message.received event with a spoofed from and arbitrary extracted_text.
  3. The agent processes the content; any reply is sent to the attacker-chosen sender_id.

Why existing protection is bypassed

There is no protection on this handler: no signature verification, no webhooks_require_verification() gate, no auth. Sender allow/block lists are bypassed because from is attacker-controlled.

Security boundary

Unauthenticated network peer → agent message pipeline + reply destination. Crosses the bot's inbound trust boundary (provider webhooks are expected to be signed/authenticated).

Proof of Concept

Environment

Real AgentMailBot._handle_email_webhook mounted in a local runtime (127.0.0.1:18080); the agent layer is a canary recorder (/webhook-log). No real email is sent. Runnable assets: PraisonAI-Runtime-Repro\runtime-files\.

Steps to reproduce

  1. PRAI-03-01-Webhook-Spoofed-Sender:
POST /webhook HTTP/1.1
Host: 127.0.0.1:18080
Content-Type: application/json

{"type":"message.received","data":{"from":"attacker@evil.example","extracted_text":"PRAISONAI_WEBHOOK_INJECT_CANARY_7f3a91 ...","subject":"hello","headers":{}}}
  1. PRAI-03-02-Agent-Reached-Response: GET /webhook-log.

Expected result

The webhook should reject unsigned/unauthenticated events; spoofed senders should not reach the agent.

Actual result

  • POST /webhook200 OK (no auth/signature).
  • GET /webhook-log{"reached_agent":[{"sender":"attacker@evil.example","content":"...PRAISONAI_WEBHOOK_INJECT_CANARY_7f3a91...","source":"webhook"}],"count":1}.

Impact

Unauthenticated message injection into the agent; sender spoofing (access-control bypass); agent reply/exfiltration to an attacker-chosen address; prompt-injection surface; LLM cost abuse. If the agent has dangerous tools, escalation via prompt injection is possible.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L

CVE ID

No known CVE

Weaknesses

Authentication Bypass by Spoofing

This attack-focused weakness is caused by incorrectly implemented authentication schemes that are subject to spoofing attacks. Learn more on MITRE.

Insufficient Verification of Data Authenticity

The product does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data. Learn more on MITRE.

Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action. Learn more on MITRE.

Credits