Every CVE Search/ Get API key

CVE-2026-47395

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

5.5 MediumFix available

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, 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 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. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a fix.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
Required

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.18%Up 0.2 points since Jun 12, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.5

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

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, 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 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. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a fix.

Record
CVE-2026-47395
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness
CWE-200
Updated
2026-11-02
EUVDEUVD-2026-46303 5.5

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, 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 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. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a fix.

Record
EUVD-2026-46303
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-5cxw-77wg-jrf3 5.5

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 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…
Record
GHSA-5cxw-77wg-jrf3
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness
CWE-200
Updated
2026-11-02
NVD 5.5

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, 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 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. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a fix.

Record
CVE-2026-47395
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness
CWE-200
Updated
2026-11-02
OSV 5.5

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

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, 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 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. PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain a fix.

Record
CVE-2026-47395
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness
CWE-200
Updated
2026-11-02
OSVGHSA-5cxw-77wg-jrf3 5.5

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 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…
Record
GHSA-5cxw-77wg-jrf3
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Weakness
CWE-200
Updated
2026-11-02
OSVPYSEC-2026-2903 5.5

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 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…
Record
PYSEC-2026-2903
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Updated
2026-11-02
OSVPYSEC-2026-2942 5.5

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 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…
Record
PYSEC-2026-2942
CVSS 3.1
5.5 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
praisonaiagents
PyPI
through 1.6.39
1.6.40
praisonai
PyPI
through 4.6.39
4.6.40
praisonaiagents
PyPI
before 1.6.40, plus listed versions
0.0.10.0.100.0.1000.0.1010.0.102
Show 45 moreShow less
0.0.1030.0.1040.0.1050.0.1060.0.1070.0.1080.0.1090.0.110.0.1100.0.1110.0.1120.0.1130.0.1140.0.1150.0.1160.0.1170.0.1180.0.1190.0.120.0.1200.0.1210.0.1220.0.1230.0.1240.0.1250.0.1260.0.1270.0.1280.0.1290.0.130.0.1300.0.1310.0.1320.0.1330.0.1340.0.1350.0.1360.0.1370.0.1380.0.1390.0.140.0.1400.0.1410.0.1420.0.143
1.6.40
praisonai
PyPI
before 4.6.40, plus listed versions
0.0.10.0.100.0.110.0.120.0.13
Show 45 moreShow less
0.0.140.0.150.0.160.0.170.0.180.0.190.0.20.0.200.0.210.0.220.0.230.0.240.0.250.0.260.0.270.0.280.0.290.0.30.0.300.0.310.0.320.0.330.0.340.0.350.0.360.0.370.0.380.0.390.0.40.0.400.0.410.0.420.0.430.0.440.0.450.0.460.0.470.0.480.0.490.0.50.0.500.0.520.0.530.0.540.0.55
4.6.40

History

History
RecordedChangedSources
aliasesEUVD
first indexedCVE List, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-47395 is a medium vulnerability (CVSS 5.5) in Mervinpraison Praisonai, published May 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.18%, the 7th percentile. Fixed in praisonaiagents 1.6.40.

References

This page doesn't list everything

Left out here: 1,199 versions and the rest of 4 source descriptions. The JSON record has them.

MoveEnter Open