piccolo SQL Injection via named transaction savepoints
Date: 2023-11
Affected: pip/piccolo
Attack vector: sql-injection
Category: vulnerability-disclosure
Severity: Critical
CVE: CVE-2023-47128
CWE: CWE-89
CVSS: 9.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)

### Summary The handling of named transaction savepoints in all database implementations is vulnerable to [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection) as user provided input is passed directly to `connection.execute(...)` via f-strings. ### Details An excerpt of the Postgres savepoint handling: ```python async def savepoint(self, name: t.Optional[str] = None) -> Savepoint: name = name or f"savepoint_{self.get_savepoint_id()}" await self.connection.execute(f"SAVEPOINT {name}") return Savepoint(name=name, transaction=self) ``` In this example, we can see user input is directly passed to `connection.execute` without being properly escaped. All implementations of savepoints and savepoint methods directly pass this `name` parameter to `connection.execute` and are vulnerable to this. A non-exhaustive list can be found below: - Postgres - - [One](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/postgres.py#L239) - - [Two](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/postgres.py#L133) - - [Three](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/postgres.py#L138) - Sqlite - - [One](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/sqlite.py#L416) - - [Two](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/sqlite.py#L313) - - [Three](https://github.com/piccolo-orm/piccolo/blob/master/piccolo/engine/sqlite.py#L318) Care should be given to ens


Mitigations:

Architectural layers (MAESTRO):