GHSA-rg3h-x3jw-7jm5: PraisonAI: SQL Injection via unvalidated `table_prefix` in 9 conversation store backends (incomplete fix for CVE-2026-40315)
The fix for [CVE-2026-40315](https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-x783-xp3g-mqhp) added input validation to `SQLiteConversationStore` only. Nine sibling backends — MySQL, PostgreSQL, async SQLite/MySQL/PostgreSQL, Turso, SingleStore, Supabase, SurrealDB — pass `table_prefix` straight into f-string SQL. Same root cause, same code pattern, same exploitation. 52 unvalidated injection points across the codebase.`postgres.py` additionally accepts an unvalidated `schema` parameter used directly in DDL.Severity**High** — CWE-89 (SQL Injection)CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N — **8.1**Exploitable in any deployment where `table_prefix` is derived from external input (multi-tenant setups, API-driven configuration, user-modifiable config files). Default config (`"praison_"`) is not affected.DetailsThe [CVE-2026-40315 fix](https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-x783-xp3g-mqhp) added this guard to `sqlite.py:52`:The following backends perform the identical `table_prefix → f-string SQL` pattern **without this guard**:| Backend          | File                                         | Line            | Injection points        |
| ---------------- | -------------------------------------------- | --------------- | ----------------------- |
| MySQL            | `persistence/conversation/mysql.py`          | 65              | 5                       |
| PostgreSQL       | `persistence/conversation/postgres.py`       | 89 (+schema:88) | 10                      |
| Async SQLite     | `persistence/conversation/async_sqlite.py`   | 43              | 13                      |
| Async MySQL      | `persistence/conversation/async_mysql.py`    | 65              | 13                      |
| Async PostgreSQL | `persistence/conversation/async_postgres.py` | 63              | 13                      |
| Turso/LibSQL     | `persistence/conversation/turso.py`          | 66              | 9                       |
| SingleStore      | `persistence/conversation/singlestore.py`    | 51              | 7                       |
| Supabase         | `persistence/conversation/supabase.py`       | 68              | 9                       |
| SurrealDB        | `persistence/conversation/surrealdb.py`      | 57              | 8                       |
| **Total**        | **9 backends**                               |                 | **52 injection points** |Additionally, `praisonai-agents/praisonaiagents/storage/backends.py:179` (`SQLiteBackend`) accepts `table_name` without validation.PoCOutput:Vulnerable code (mysql.py, representative)Compare with the patched `sqlite.py:52`:ImpactWhen `table_prefix` originates from untrusted input — multi-tenant tenant names, API request parameters, user-editable config — an attacker achieves **arbitrary SQL execution** against the backing database. The injected SQL runs in the context of DDL and DML operations (CREATE TABLE, INSERT, SELECT, DELETE), giving the attacker read/write/delete access to the entire database.PostgreSQL's `schema` parameter adds a second injection vector in DDL (`CREATE SCHEMA IF NOT EXISTS {schema}`).
CVSS v3.1: 8.1