PraisonAI: AgentMailのWebhook機能には署名検証の欠陥があり、認証されていないメッセージの挿入や送信者のなりすましを許してしまう。

## 概要

PraisonAIのAgentMailボットが、Webhook(またはハイブリッド)モードで動作する場合、`0.0.0.0`にバインドされたaiohttpのWebhookサーバーが起動し、受信する`message.received`イベントを**署名/HMACの検証や認証なしに処理する**。送信者のアドレスとメッセージの内容は、攻撃者が制御するリクエストボディから直接取得されるため、ネットワーク上のどのノードからも、なりすました送信者アドレスでメッセージをボットに挿入することが可能であり、ボットはその内容を処理し、攻撃者が指定したアドレスに返信してしまう。関連する他のボット(`linear.py`、`whatsapp.py`)は、シークレットが設定されていない場合に動作を停止するが、AgentMailはチェック自体を省略している。実行による確認済み。深刻度は中程度。

## 詳細

### 影響を受けるコンポーネント
- パッケージ: `praisonai` 4.6.63。ファイル: `src/praisonai/praisonai/bots/agentmail.py` (`AgentMailBot`、Webhook/ハイブリッドモード)。

### 脆弱なコード / 根本原因

パス:
`src/praisonai/praisonai/bots/agentmail.py`

関数:
`_start_webhook_mode` / `_handle_email_webhook` / `_handle_message`

コードスニペット:
```python
# _start_webhook_mode: すべてのインターフェースにバインド
self._webhook_site = web.TCPSite(self._webhook_runner, "0.0.0.0", self._webhook_port)

# _handle_email_webhook: 署名/HMACのチェックなし、認証なし
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)) # 攻撃者のボディを送信
return web.Response(status=200, text="OK")
```

```
# _handle_message: エージェントがコンテンツを処理し、攻撃者によって制御された送信元に対して応答します。
response = await self._session.chat(self._agent, sender_id, body, ...)
await self.send_message(channel_id=sender_id, ...)
```
問題点: 攻撃者によって制御される入力が、生のWebhook JSONデータ(`from`、`extracted_text`、`subject`)です。本来存在すべきであるはずの保護機能であるプロバイダーの署名検証機能が**存在しません**(svix/HMACの利用がない、`webhooks_require_verification()`の呼び出しがない)。データが処理される箇所は、`self._session.chat(self._agent, ...)`(エージェントの呼び出し)と、`send_message(channel_id=sender_id, ...)`(偽装された送信元への応答)です。関連するハンドラである`src/praisonai/praisonai/bots/linear.py`と`bots/whatsapp.py`では、`webhooks_require_verification()`が呼び出され、シークレットが設定されていない場合は拒否されます。しかし、AgentMailではそれがなく、結果として許可されてしまいます。

### 攻撃の流れ
1. 運用担当者が、AgentMailボットをWebhook/ハイブリッドモードで実行します(ドキュメントに記載あり。`0.0.0.0`にバインドされ、デフォルトのパスは`/webhook`、デフォルトのポートは8080)。
2. 攻撃者が、偽装された`from`と任意の`extracted_text`を含む、細工された`message.received`イベントをPOSTします。
3. エージェントがコンテンツを処理し、その応答は攻撃者が指定した`sender_id`に送信されます。

### 既存の保護が回避される理由
このハンドラには、署名検証、`webhooks_require_verification()`の呼び出し、認証などの保護機能が一切ありません。送信元を許可/ブロックするリストも回避されます。なぜなら、`from`が攻撃者によって制御されるからです。

### セキュリティ境界
認証されていないネットワークピア → エージェントメッセージパイプライン + 応答先。ボットのインバウンド信頼境界を越えます(プロバイダーのWebhookは署名または認証されていることが期待されます)。

## 実証
### 環境
`AgentMailBot._handle_email_webhook`がローカルの実行環境(`127.0.0.1:18080`)にマウントされています。エージェントレイヤーは、カメレオンレコーダー(`/webhook-log`)として機能します。実際のメールは送信されません。実行可能なファイルは、`PraisonAI-Runtime-Repro\runtime-files\`にあります。

### 再現手順
1. `PRAI-03-01-Webhook-Spoofed-Sender`:
```http
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":{}}}
2. `PRAI-03-02-Agent-Reached-Response`: `GET /webhook-log`.

### 期待される結果
Webhookは、署名されていない/認証されていないイベントを拒否する必要があります。なりすましの送信元からのリクエストがエージェントに到達してはなりません。

### 実際の状況
- `POST /webhook` → `200 OK` (認証/署名なし)。
- `GET /webhook-log` → `{"reached_agent":[{"sender":"attacker@evil.example","content":"...PRAISONAI_WEBHOOK_INJECT_CANARY_7f3a91...","source":"webhook"}],"count":1}`。

## 影響
エージェントへの認証されていないメッセージの注入、送信元のなりすまし(アクセス制御の回避)、攻撃者が指定した宛先へのエージェントからの応答/データ送信、プロンプトインジェクションの脆弱性、LLMのコスト不正利用。エージェントが危険なツールを持っている場合、プロンプトインジェクションによるエスカレーションが可能です。

影響を受けるパッケージ:
- pip (Python) praisonai: 影響を受けるバージョンは4.6.77以下、4.6.78で修正済み。