Skip to content

False negative: py/sql-injection misses sqlite3 cursor.execute when the cursor is stored on an instance attribute (CVE-2025-55156) #21766

@invoke1442

Description

@invoke1442

Description of the false negative

py/sql-injection seems to miss a sqlite3/PEP249 pattern where the cursor is created in one method, stored on self, and then used from another method.

This came up while looking at CVE-2025-55156:

In the real-world case, user-controlled input eventually reaches:

self.c.execute(f"SELECT id FROM links WHERE url IN ('{statuses}')")

Here is a simplified minimal example:

from flask import Flask, request  # $ Source
import sqlite3

app = Flask(__name__)

class Repo:
    def __init__(self):
        self.conn = sqlite3.connect(":memory:")
        self.c = self.conn.cursor()

    def lookup(self, value):
        self.c.execute(f"SELECT id FROM links WHERE url IN ('{value}')")  # $ Alert

repo = Repo()

@app.route("/lookup")
def lookup():
    value = request.args.get("value", "")
    repo.lookup(value)
    return "ok"

Expected behavior: an alert on the execute(...) call.

Actual behavior: no alert.

sqlite3 and PEP249 execute calls already seem to be modeled, so this looks like the receiver is not being recognized once the cursor is stored on an instance attribute.

This does not seem like a one-off pattern. Recent Python SQL injection CVEs keep showing the same basic issue: attacker-controlled data ends up in string-built SQL in sqlite/Python code, just through slightly different plumbing. A few examples:

  • CVE-2026-21892 (Parsl): SQL built with Python % formatting from a route parameter
  • CVE-2026-33545 (MobSF): SQL built with Python % formatting from attacker-controlled table names
  • CVE-2025-67644 (LangGraph SQLite Checkpoint): SQL built with f-strings from attacker-controlled metadata keys

So even though this specific case uses self.c, the broader pattern is common enough that it would be useful if py/sql-injection covered it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions