A high-severity SQL injection vulnerability (CVE-2026-41496) has been disclosed in PraisonAI, a popular Python-based multi-agent AI framework, revealing that a previous security patch for CVE-2026-40315 only partially addressed the root cause, leaving nine conversation store backends exposed to arbitrary SQL execution across 52 unvalidated injection points.
PraisonAI is an open-source multi-agent orchestration framework distributed via PyPI under the packages praisonai and praisonaiagents.
It is widely used for building multi-agent AI pipelines with persistent conversation storage backed by databases such as SQLite, MySQL, PostgreSQL, Turbo, SingleStore, Supabase, and SurrealDB.
The framework’s multi-tenant capabilities, which table_prefix can be dynamically supplied per tenant, make this SQL injection flaw particularly dangerous in production deployments.
CVE-2026-41496: PraisonAI SQL Injection Vulnerability
The predecessor vulnerability, CVE-2026-40315, was disclosed in April 2026 and involved SQLiteConversationStore directly concatenating a user-supplied table_prefix value into SQL queries via Python f-strings, without any input validation.
The patch for that flaw added a single regex guard inside sqlite.py at line 52, rejecting any table_prefix that contained non-alphanumeric characters. However, security researchers discovered that the fix was applied exclusively to the SQLite backend while eight other sibling backends received no equivalent protection.
import re
if not re.match(r'^[a-zA-Z0-9_]*$', table_prefix):
raise ValueError("table_prefix must contain only alphanumeric characters and underscores")
Every other backend MySQL, PostgreSQL, async SQLite, async MySQL, async PostgreSQL, Turso/LibSQL, SingleStore, Supabase, and SurrealDB passes table_prefix directly into f-string SQL identifiers with zero validation.
The vulnerability is tracked as GHSA-rg3h-x3jw-7jm5 and assigned CVE-2026-41496, rated High severity with a CVSS v3.1 score of 8.1 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N). The affected files and injection point counts are as follows:
| Backend | File | Injection Points |
|---|---|---|
| MySQL | persistence/conversation/mysql.py:65 | 5 |
| PostgreSQL | persistence/conversation/postgres.py:89 | 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 |
PostgreSQL introduces a second injection vector: the schema parameter in postgres.py:88 is also passed without validation directly into DDL statements (CREATE SCHEMA IF NOT EXISTS {schema}).
Additionally, praisonaiagents/storage/backends.py:179 (SQLiteBackend) accepts a table_name parameter without any validation.
The attack exploits the fact that SQL identifiers, table names, and schema names cannot be safely parameterized using standard prepared statement mechanisms, unlike query values.
When table_prefix is derived from external input (multi-tenant tenant IDs, API request parameters, or user-modifiable config files), an attacker can inject malicious SQL fragments directly into DDL and DML operations, including CREATE TABLE, INSERT, SELECT, and DELETE.
The proof-of-concept demonstrates this starkly. Injecting the payload x'; DROP TABLE users; -- into the MySQL backend generates the following destructive SQL without any error:
CREATE TABLE IF NOT EXISTS x'; DROP TABLE users; --sessions (session_id VARCHAR(255) PRIMARY KEY)
For PostgreSQL, a schema injection payload of public; DROP SCHEMA data CASCADE; -- results in:
CREATE SCHEMA IF NOT EXISTS public; DROP SCHEMA data CASCADE; --
This grants an attacker with low-privilege access full read, write, and delete access to the entire backing database. Deployments using the default table_prefix value of "praison_" from hardcoded configuration are not affected.
Affected Versions and Patch
Both PyPI packages are affected across a wide range of versions.
praisonai: All versions<= 4.6.8are vulnerable; upgrade to>= 4.6.9praisonaiagents: All versions<= 1.6.8are vulnerable; upgrade to>= 1.6.9
Organizations that stopped at praisonai 4.5.133 (the CVE-2026-40315 patch) remain fully exposed to this vulnerability. Administrators should immediately upgrade via pip install --upgrade praisonai praisonaiagents and audit all deployment configurations to confirm that table_prefix is not derived from user-controlled input.
Until patching is complete, enforce strict allowlist validation on table_prefix at the application layer using the regex pattern. ^[a-zA-Z0-9_]*$.
FAQ
Q1: What is CVE-2026-41496?
CVE-2026-41496 is a high-severity SQL injection vulnerability (CVSS 8.1) in PraisonAI caused by an incomplete fix for CVE-2026-40315, leaving nine database backends with unvalidated table_prefix parameters that allow arbitrary SQL execution.
Q2: Which versions of PraisonAI are affected by this vulnerability?
praisonai versions <= 4.6.8 and praisonaiagents versions <= 1.6.8 are affected; users must upgrade to >= 4.6.9 and >= 1.6.9 respectively to be protected.
Q3: Does this vulnerability affect default PraisonAI installations?
No, deployments using the hardcoded default table_prefix value of "praison_" are not at risk; only deployments where table_prefix is derived from external, user-controlled input are exploitable.
Q4: How can organizations mitigate CVE-2026-41496 if immediate patching is not possible?
Organizations should apply strict allowlist input validation on table_prefix using the regex ^[a-zA-Z0-9_]*$ at the application layer, restrict database user permissions to least-privilege, and avoid exposing table_prefix configuration to any external or user-controlled input source.
Site: thecybrdef.com
For more insights and updates, follow us on Google News, Twitter, and LinkedIn.