Skip to main content

PraisonAI CVE-2026-44335

HIGH
Server-Side Request Forgery (SSRF) (CWE-918)
2026-05-06 https://github.com/MervinPraison/PraisonAI GHSA-q9pw-vmhh-384g
7.7
CVSS 4.0 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.7 HIGH
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
vuln.today AI
7.5 HIGH

Network-reachable, low-complexity, unauthenticated URL-parser bypass with no user interaction; impact bounded to integrity (forged internal requests) with confidentiality/availability not clearly established, matching the vendor's integrity-focused scoring.

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

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
X

Lifecycle Timeline

5
Source Code Evidence Fetched
Jul 23, 2026 - 23:13 vuln.today
Analysis Generated
Jul 23, 2026 - 23:13 vuln.today
CVSS changed
May 08, 2026 - 14:22 NVD
7.7 (HIGH)
CVE Published
May 06, 2026 - 22:08 github-advisory
HIGH 7.7
CVE Published
May 06, 2026 - 22:08 nvd
HIGH

DescriptionGitHub Advisory

Summary

The URL checking logic in PraisonAI has a logical flaw that could be bypassed by attackers, leading to SSRF attacks.

Details

The current PraisonAI project uses _validate_url to validate the input URL. The main logic is to perform security checks on the host portion of the URL extracted by urlparse to prevent SSRF attacks.

<img width="1290" height="1145" alt="QQ20260424-151256-24-1" src="https://github.com/user-attachments/assets/d5f16b74-5ad2-444f-8600-b05f78a4b769" />

However, there are indeed differences in parsing between urlparse and the library that actually sends the request. Currently, almost all application scenarios in this project involve first using _validate_url for URL validation, and then using _get_session().get to send the request.

<img width="1143" height="740" alt="QQ20260424-151437-24-2" src="https://github.com/user-attachments/assets/b1bf6ec2-d32a-4dac-b814-da819e8d3c83" />

In reality, its underlying mechanism is requests.get.

<img width="1042" height="576" alt="QQ20260424-151645-24-3" src="https://github.com/user-attachments/assets/e17352c3-4205-44d6-ab6e-75566480215b" />

The core issue: urlparse() and requests disagree on which host a URL like http://127.0.0.1:6666\@1.1.1.1 points to:

  • urlparse() treats \ as a regular character and @ as the userinfo-host delimiter, so it extracts hostname as 1.1.1.1 (public)
  • requests treats \ as a path character, connecting to 127.0.0.1 (internal)

Below is a test code I wrote following the code.

import sys
from pathlib import Path
from pprint import pprint

sys.path.insert(0, str(Path(r"D:/BaiduNetdiskDownload/PraisonAI-main/PraisonAI-main/src/praisonai-agents")))

from praisonaiagents.tools import spider_tools
# url = "http://127.0.0.1:6666\@1.1.1.1"
url = "http://127.0.0.1:6666"

result = spider_tools.scrape_page(url)

if isinstance(result, dict) and "error" in result:
    print("scrape failed:", result["error"])
else:
    pprint(result)

When an attacker uses http://127.0.0.1:6666/, the existing detection logic can detect that this is an internal network address and block it.

<img width="1068" height="128" alt="QQ20260424-152007-24-4" src="https://github.com/user-attachments/assets/294bff10-2af6-4960-bf69-dbf3340b1e9b" />

However, when an attacker uses http://127.0.0.1:6666\@1.1.1.1, the detection logic resolves the host to 1.1.1.1, which is a public IP address, thus passing the verification. But in the actual request process, this URL is forwarded by requests.get to http://127.0.0.1:6666, bypassing the detection and achieving an SSRF attack.

<img width="2089" height="324" alt="QQ20260424-152123-24-5" src="https://github.com/user-attachments/assets/4421ce42-e47b-48de-a97a-56ce56a2bbc9" />

PoC

http://127.0.0.1:6666\@1.1.1.1

Impact

SSRF

AnalysisAI

Server-side request forgery in PraisonAI (praisonaiagents Python package, versions <= 1.6.31) lets remote attackers bypass the framework's SSRF protections by exploiting a URL-parsing differential between Python's urlparse and the requests library. The _validate_url anti-SSRF check resolves a payload like http://127.0.0.1:6666\@1.1.1.1 to the public host 1.1.1.1 and allows it, but requests.get actually connects to the internal 127.0.0.1, so the agent's scraping tools can be coerced into reaching internal services. Publicly available exploit code exists (a working PoC is published in the GHSA advisory), though EPSS is very low (0.04%, 13th percentile) and there is no evidence of active exploitation.

Technical ContextAI

The flaw is a classic CWE-918 SSRF caused by a parser-confusion vulnerability. PraisonAI attempts to block requests to internal addresses by extracting the host with urlparse().hostname and validating it, then issuing the outbound request through _get_session().get, which is backed by the requests library. urlparse and requests apply different URL grammar to the same string: urlparse treats the backslash as an ordinary character and the '@' as the userinfo/host delimiter, extracting 1.1.1.1 as the host, while requests (following WHATWG/curl-style normalization) treats the backslash as a path separator and connects to the authority before it, 127.0.0.1:6666. Because validation and request-sending use two libraries that disagree on the effective host, any allow-list/deny-list check on the parsed host can be desynchronized from the real connection target. The affected component is the praisonaiagents pip package (pkg:pip/praisonaiagents), specifically its spider_tools/scrape_page and other tools that fetch attacker-influenced URLs.

RemediationAI

Upgrade the praisonaiagents package to the patched release - Vendor-released patch: 1.6.32 (pip install --upgrade 'praisonaiagents>=1.6.32'), per GHSA-q9pw-vmhh-384g. If you cannot upgrade immediately, reduce exposure by not passing user-controlled URLs into the scraping/fetch tools (e.g. spider_tools.scrape_page), or place the tool behind validation that resolves and pins the host with the same library that sends the request (requests) rather than urlparse, rejecting URLs whose resolved connection target is loopback, link-local (169.254.0.0/16 including 169.254.169.254 metadata), or RFC1918 space; note this changes behavior for any legitimate internal-URL use cases. Additionally, restrict outbound egress from the host running PraisonAI via a network egress allow-list or an outbound proxy so that even a successful bypass cannot reach internal services or cloud metadata endpoints - the trade-off is that legitimate outbound fetches must be explicitly permitted. Reject URLs containing backslashes or embedded userinfo ('@') as a targeted stopgap for this specific payload class. Advisory: https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-q9pw-vmhh-384g.

Share

CVE-2026-44335 vulnerability details – vuln.today

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