{"id":"GHSA-c969-5x3p-vq3v","title":"PraisonAI: IMAP Command Injection via Unsanitized Email Search Parameters","summary":"PraisonAI: IMAP Command Injection via Unsanitized Email Search Parameters","severity":"high","cvss":8.1,"cwe":["CWE-20","CWE-77"],"vendor":"praisonaiagents","product":"praisonaiagents","affected":["praisonaiagents <= 1.6.48"],"patched":["praisonaiagents 1.6.59"],"published":"2026-06-18","updated":"2026-06-18","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-c969-5x3p-vq3v","references":[{"url":"https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-c969-5x3p-vq3v"},{"url":"https://github.com/advisories/GHSA-c969-5x3p-vq3v"}],"tags":["ghsa","pip"],"ingestedAt":"2026-06-19T03:39:00.842Z","ecosystem":"pip","slug":"GHSA-c969-5x3p-vq3v","body":"## Overview\n\n## Summary\n\nThe email search tool in `src/praisonai-agents/praisonaiagents/tools/email_tools.py` constructs IMAP SEARCH commands by interpolating LLM-controlled parameters (from_addr, subject, query) directly into IMAP protocol strings using f-string formatting with double-quote delimiters. An attacker who can influence the arguments to the `search_emails` or `reply_email` tool (via crafted agent prompts) can inject arbitrary IMAP commands, potentially exfiltrating email data from other folders, deleting emails, or performing other unauthorized IMAP operations.\n## Details\n\n**Vulnerable code (lines 493–502):**\n```python\ncriteria = []\nif from_addr:\n    criteria.append(f'FROM \"{from_addr}\"')\nif subject:\n    criteria.append(f'SUBJECT \"{subject}\"')\nif query:\n    criteria.append(f'TEXT \"{query}\"')\nif not criteria:\n    criteria.append(\"ALL\")\nsearch_str = \" \".join(criteria)\nstatus, data = mail.search(None, search_str)\n```\n\nThe `from_addr`, `subject`, and `query` parameters originate from LLM tool call arguments (the `search_emails` public function at line 665). These values flow through without any sanitization or escaping. The double-quote (`\"`) characters in these parameters allow breaking out of the IMAP SEARCH quoted string context.\n\n**Additional injection points:**\n- Line 416: `mail.search(None, f'HEADER Message-ID \"{search_id}\"')`\n- Line 447: Same pattern in `_smtp_reply_email`\n- Line 542: Same pattern in `_smtp_archive_email`\n\nThe `search_id` / `message_id` parameter in these functions is also LLM-controlled via the `reply_email` and `archive_email` public tool functions.\n\n**Reachability:** The `search_emails`, `reply_email`, and `archive_email` functions are exposed as agent tools. They are reachable when an agent is configured with email tools (EMAIL_ADDRESS + EMAIL_PASSWORD environment variables set). This is a documented deployment scenario for email-capable agents.\n\n## PoC\n\n**Setup:** Requires an IMAP server (not run here — this is a static proof). The vulnerability is demonstrated by tracing the data flow.\n\n**Positive trigger — IMAP injection via `search_emails`:**\nAn LLM agent processing a crafted prompt calls:\n```python\nsearch_emails(from_addr='user@example.com\" LOGOUT')\n```\nThis produces the IMAP command:\n```\nSEARCH FROM \"user@example.com\" LOGOUT\"\n```\nThe `LOGOUT` command is injected after the prematurely closed quoted string, causing the IMAP connection to be terminated.\n\n**More severe injection — exfiltrate emails from another folder:**\n```python\nsearch_emails(query='\" SEARCH RETURN (MIN) ALL')\n```\nProduces: `TEXT \"\" SEARCH RETURN (MIN) ALL\"` — injects a secondary SEARCH command.\n\n**Negative control — legitimate search:**\n```python\nsearch_emails(from_addr='user@example.com')\n```\nProduces: `FROM \"user@example.com\"` — correct, no injection.\n\n**Cleanup:** No persistent changes for read-only injection. For destructive injection (DELETE, EXPUNGE), impact persists.\n\n## Impact\n\nAn attacker who can craft prompts that cause an LLM agent to call `search_emails` with injection payloads can:\n\n- **Terminate IMAP connections** (denial of service)\n- **Inject arbitrary IMAP commands** — including LIST (enumerate folders), SELECT (switch folders), FETCH (read emails from other mailboxes), STORE (modify flags), COPY/MOVE (move emails), DELETE/EXPUNGE (permanently delete emails)\n- **Exfiltrate email contents** from folders the user did not intend to expose to the agent\n- **Permanently delete emails** via injected DELETE + EXPUNGE commands\n\nThe attack requires the IMAP backend to be configured (EMAIL_ADDRESS + EMAIL_PASSWORD env vars), which is a documented and common deployment for email-capable agents.\n\n## Suggested remediation\n\n1. **Escape double-quote characters** in IMAP parameters. Per RFC 3501, literal strings use `{n}\\r\\n` format or quoted strings with `\\` escaping:\n```python\ndef _escape_imap_string(s: str) -> str:\n    \"\"\"Escape a string for safe use in IMAP quoted strings.\"\"\"\n    # Use IMAP literal syntax for safety: {length}\\r\\n<data>\n    encoded = s.encode('utf-8')\n    return f'{{{len(encoded)}}}\\r\\n{encoded}'\n```\n\n2. Use IMAP literal syntax (`{n}\\r\\ndata`) instead of quoted strings for all user-controlled parameters. This prevents any injection regardless of content.\n\n3. Apply the escaping to all IMAP search criteria parameters: `from_addr`, `subject`, `query`, and `search_id`/`message_id`.\n\n## Affected packages\n\n- `praisonaiagents <= 1.6.48`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `praisonaiagents 1.6.59`","depth":"twilight","depthScore":45,"depthScoreParts":{"impact":44.6,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}