Every CVE Search/ Get API key

CVE-2026-56834

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

7.5 HighFix available

PraisonAI is a multi-agent teams system. From version 3.8.1 to before version 4.6.59, PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools(). The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem. As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data. This issue has been patched in version 4.6.59.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.37%Down 0.1 points since Oct 24, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

PraisonAI is a multi-agent teams system. From version 3.8.1 to before version 4.6.59, PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools(). The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem. As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data. This issue has been patched in version 4.6.59.

Record
CVE-2026-56834
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22, CWE-200
Updated
2026-11-02
EUVDEUVD-2026-108875 7.5

PraisonAI is a multi-agent teams system. From version 3.8.1 to before version 4.6.59, PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools(). The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem. As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data. This issue has been patched in version 4.6.59.

Record
EUVD-2026-108875
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-j7qx-p75m-wp7g 7.5

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

Summary

PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools():

ctx = setup_dynamic_context()

agent = Agent(
    instructions="You are a data analyst.",
    tools=ctx.get_tools(),
    hooks=[ctx.get_middleware()],
)

The official documentation describes these helpers as a way for the agent to explore large tool-output artifacts that were queued by the middleware:

  • large tool outputs are saved as artifacts;
  • the agent receives compact artifact references; and
  • the agent uses artifact_tail and artifact_grep to explore that data.

The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem.

As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data.

Affected Product

  • Repository: MervinPraison/PraisonAI
  • Ecosystem: pip
  • Package: praisonai
  • Component: Dynamic Context Discovery artifact tools
  • Current source path: src/praisonai/praisonai/context/queue.py
  • Artifact store path: src/praisonai/praisonai/context/artifact_store.py
  • Latest PyPI version validated: 4.6.58
  • Current origin/main validated: 1ad58ca02975ff1398efeda694ea2ab78f20cf3e
  • Current origin/main tag validated: v4.6.58

Suggested affected range:

pip:praisonai >= 3.8.1, <= 4.6.58

Representative local sweep:

  • 3.8.1: vulnerable
  • 4.0.0: vulnerable
  • 4.5.113: vulnerable
  • 4.6.33: vulnerable
  • 4.6.34: vulnerable
  • 4.6.40: vulnerable
  • 4.6.50: vulnerable
  • 4.6.58: vulnerable

Root Cause

create_artifact_tools() creates an artifact store bound to base_dir, but the read tools do not use base_dir for containment.

For example, artifact_head() accepts artifact_path and immediately creates an ArtifactRef with that path:

def artifact_head(artifact_path: str, lines: int = 50) -> str:
    ref = ArtifactRef(path=artifact_path, summary="", size_bytes=0)
    try:
        return artifact_store.head(ref, lines=lines)
    except FileNotFoundError:
        return f"Error: Artifact not found: {artifact_path}"

artifact_tail(), artifact_grep(), and artifact_chunk() have the same pattern. They trust the caller-supplied path rather than resolving it through an artifact identifier, store lookup, manifest, or base-directory containment check.

The store methods then read that path directly:

def head(self, ref: ArtifactRef, lines: int = 50) -> str:
    file_path = Path(ref.path)
    if not file_path.exists():
        raise FileNotFoundError(f"Artifact not found: {ref.path}")

    result_lines = []
    with open(file_path, "r", encoding="utf-8", errors="replace") as f:
        ...

There is no check equivalent to:

resolved = Path(ref.path).resolve()
base = self.base_dir.resolve()
resolved.relative_to(base)

There is also no check that the file has a valid .meta sidecar or appears in artifact_list().

Local PoV

Run against the latest PyPI package:

uv run --with 'praisonai==4.6.58' \
  python poc/pov_prai_cand_026_artifact_tools_arbitrary_file_read.py --json

The PoV:

  1. Creates a temporary artifact base directory.
  2. Creates a separate outside-secret.txt file outside that base directory.
  3. Stores one legitimate artifact through FileSystemArtifactStore.store().
  4. Calls artifact_head() on the legitimate artifact as a positive control.
  5. Calls artifact_head(), artifact_grep(), and artifact_chunk() on…
Record
GHSA-j7qx-p75m-wp7g
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22, CWE-200
Updated
2026-11-02
NVD 7.5

PraisonAI is a multi-agent teams system. From version 3.8.1 to before version 4.6.59, PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools(). The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem. As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data. This issue has been patched in version 4.6.59.

Record
CVE-2026-56834
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-22, CWE-200
Updated
2026-11-02
OSV 7.5

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

PraisonAI is a multi-agent teams system. From version 3.8.1 to before version 4.6.59, PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools(). The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem. As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data. This issue has been patched in version 4.6.59.

Record
CVE-2026-56834
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-200, CWE-22
Updated
2026-11-02
OSVGHSA-j7qx-p75m-wp7g 7.5

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

Summary

PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools():

ctx = setup_dynamic_context()

agent = Agent(
    instructions="You are a data analyst.",
    tools=ctx.get_tools(),
    hooks=[ctx.get_middleware()],
)

The official documentation describes these helpers as a way for the agent to explore large tool-output artifacts that were queued by the middleware:

  • large tool outputs are saved as artifacts;
  • the agent receives compact artifact references; and
  • the agent uses artifact_tail and artifact_grep to explore that data.

The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem.

As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data.

Affected Product

  • Repository: MervinPraison/PraisonAI
  • Ecosystem: pip
  • Package: praisonai
  • Component: Dynamic Context Discovery artifact tools
  • Current source path: src/praisonai/praisonai/context/queue.py
  • Artifact store path: src/praisonai/praisonai/context/artifact_store.py
  • Latest PyPI version validated: 4.6.58
  • Current origin/main validated: 1ad58ca02975ff1398efeda694ea2ab78f20cf3e
  • Current origin/main tag validated: v4.6.58

Suggested affected range:

pip:praisonai >= 3.8.1, <= 4.6.58

Representative local sweep:

  • 3.8.1: vulnerable
  • 4.0.0: vulnerable
  • 4.5.113: vulnerable
  • 4.6.33: vulnerable
  • 4.6.34: vulnerable
  • 4.6.40: vulnerable
  • 4.6.50: vulnerable
  • 4.6.58: vulnerable

Root Cause

create_artifact_tools() creates an artifact store bound to base_dir, but the read tools do not use base_dir for containment.

For example, artifact_head() accepts artifact_path and immediately creates an ArtifactRef with that path:

def artifact_head(artifact_path: str, lines: int = 50) -> str:
    ref = ArtifactRef(path=artifact_path, summary="", size_bytes=0)
    try:
        return artifact_store.head(ref, lines=lines)
    except FileNotFoundError:
        return f"Error: Artifact not found: {artifact_path}"

artifact_tail(), artifact_grep(), and artifact_chunk() have the same pattern. They trust the caller-supplied path rather than resolving it through an artifact identifier, store lookup, manifest, or base-directory containment check.

The store methods then read that path directly:

def head(self, ref: ArtifactRef, lines: int = 50) -> str:
    file_path = Path(ref.path)
    if not file_path.exists():
        raise FileNotFoundError(f"Artifact not found: {ref.path}")

    result_lines = []
    with open(file_path, "r", encoding="utf-8", errors="replace") as f:
        ...

There is no check equivalent to:

resolved = Path(ref.path).resolve()
base = self.base_dir.resolve()
resolved.relative_to(base)

There is also no check that the file has a valid .meta sidecar or appears in artifact_list().

Local PoV

Run against the latest PyPI package:

uv run --with 'praisonai==4.6.58' \
  python poc/pov_prai_cand_026_artifact_tools_arbitrary_file_read.py --json

The PoV:

  1. Creates a temporary artifact base directory.
  2. Creates a separate outside-secret.txt file outside that base directory.
  3. Stores one legitimate artifact through FileSystemArtifactStore.store().
  4. Calls artifact_head() on the legitimate artifact as a positive control.
  5. Calls artifact_head(), artifact_grep(), and artifact_chunk() on…
Record
GHSA-j7qx-p75m-wp7g
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Weakness
CWE-200, CWE-22
Updated
2026-11-02
OSVPYSEC-2026-3514 7.5

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

PraisonAI dynamic-context artifact tools read arbitrary host files outside artifact storage

Summary

PraisonAI's Dynamic Context Discovery feature exposes artifact helper tools through ctx.get_tools():

ctx = setup_dynamic_context()

agent = Agent(
    instructions="You are a data analyst.",
    tools=ctx.get_tools(),
    hooks=[ctx.get_middleware()],
)

The official documentation describes these helpers as a way for the agent to explore large tool-output artifacts that were queued by the middleware:

  • large tool outputs are saved as artifacts;
  • the agent receives compact artifact references; and
  • the agent uses artifact_tail and artifact_grep to explore that data.

The implemented artifact tools do not enforce that the supplied artifact_path is an artifact created by the configured store or that it lives under the configured artifact base directory. Instead, artifact_head, artifact_tail, artifact_grep, and artifact_chunk wrap the caller-supplied path directly into an ArtifactRef and then read it from the host filesystem.

As a result, any prompt/user/tool-caller that can influence those tool arguments can read files readable by the PraisonAI process, such as project .env files, cloud credentials, SSH keys, source files, or other local data.

Affected Product

  • Repository: MervinPraison/PraisonAI
  • Ecosystem: pip
  • Package: praisonai
  • Component: Dynamic Context Discovery artifact tools
  • Current source path: src/praisonai/praisonai/context/queue.py
  • Artifact store path: src/praisonai/praisonai/context/artifact_store.py
  • Latest PyPI version validated: 4.6.58
  • Current origin/main validated: 1ad58ca02975ff1398efeda694ea2ab78f20cf3e
  • Current origin/main tag validated: v4.6.58

Suggested affected range:

pip:praisonai >= 3.8.1, <= 4.6.58

Representative local sweep:

  • 3.8.1: vulnerable
  • 4.0.0: vulnerable
  • 4.5.113: vulnerable
  • 4.6.33: vulnerable
  • 4.6.34: vulnerable
  • 4.6.40: vulnerable
  • 4.6.50: vulnerable
  • 4.6.58: vulnerable

Root Cause

create_artifact_tools() creates an artifact store bound to base_dir, but the read tools do not use base_dir for containment.

For example, artifact_head() accepts artifact_path and immediately creates an ArtifactRef with that path:

def artifact_head(artifact_path: str, lines: int = 50) -> str:
    ref = ArtifactRef(path=artifact_path, summary="", size_bytes=0)
    try:
        return artifact_store.head(ref, lines=lines)
    except FileNotFoundError:
        return f"Error: Artifact not found: {artifact_path}"

artifact_tail(), artifact_grep(), and artifact_chunk() have the same pattern. They trust the caller-supplied path rather than resolving it through an artifact identifier, store lookup, manifest, or base-directory containment check.

The store methods then read that path directly:

def head(self, ref: ArtifactRef, lines: int = 50) -> str:
    file_path = Path(ref.path)
    if not file_path.exists():
        raise FileNotFoundError(f"Artifact not found: {ref.path}")

    result_lines = []
    with open(file_path, "r", encoding="utf-8", errors="replace") as f:
        ...

There is no check equivalent to:

resolved = Path(ref.path).resolve()
base = self.base_dir.resolve()
resolved.relative_to(base)

There is also no check that the file has a valid .meta sidecar or appears in artifact_list().

Local PoV

Run against the latest PyPI package:

uv run --with 'praisonai==4.6.58' \
  python poc/pov_prai_cand_026_artifact_tools_arbitrary_file_read.py --json

The PoV:

  1. Creates a temporary artifact base directory.
  2. Creates a separate outside-secret.txt file outside that base directory.
  3. Stores one legitimate artifact through FileSystemArtifactStore.store().
  4. Calls artifact_head() on the legitimate artifact as a positive control.
  5. Calls artifact_head(), artifact_grep(), and artifact_chunk() on…
Record
PYSEC-2026-3514
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
praisonai
PyPI
3.8.1 to 4.6.58
4.6.59
praisonai
PyPI
3.8.1 up to 4.6.59, plus listed versions
3.10.03.10.13.10.103.10.113.10.12
Show 45 moreShow less
3.10.133.10.143.10.153.10.163.10.173.10.183.10.193.10.23.10.203.10.213.10.223.10.233.10.243.10.253.10.263.10.273.10.33.10.43.10.53.10.63.10.73.10.83.10.93.11.03.11.13.11.103.11.113.11.123.11.133.11.143.11.23.11.33.11.43.11.83.11.93.12.03.12.13.12.23.12.33.8.103.8.113.8.123.8.133.8.143.8.16
4.6.59

History

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

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

In short

CVE-2026-56834 is a high vulnerability (CVSS 7.5) in Mervinpraison Praisonai, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 31st percentile. Fixed in praisonai 4.6.59.

References

This page doesn't list everything

Left out here: 249 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open