FlawOpen

flawopen.com/SQL Injection en Python/SQLAlchemy

¿SQLAlchemy text() es seguro frente a SQL Injection?

Guía de referencia
Respuesta breve

Un parámetro enlazado es como una ficha sellada en un formulario de consulta: SQLAlchemy pasa la instrucción SQL y su mapa de parámetros al DBAPI subyacente, manteniendo los valores fuera de la expresión SQL que construye tu código. El controlador DBAPI realiza el enlace específico de la base de datos, por lo que el transporte puede variar. text() acepta texto SQL, pero no sanea ni parametriza valores que ya hayas interpolado en ese texto.

INSEGURO — interpolar la entrada en SQL
stmt = text(
  f"SELECT id FROM users WHERE id = {user_id}"
)
rows = conn.execute(stmt)
PROTEGIDO — enlazar valores y limitar la estructura SQL
stmt = text(
  "SELECT id FROM users WHERE id = :id"
)
rows = conn.execute(stmt, {"id": user_id})

# Bind values, not identifiers. Choose any
# selectable column from a fixed application map.
columns = {"name": users.c.name,
           "created": users.c.created_at}
column = columns.get(requested_sort, users.c.created_at)
stmt = select(users.c.id).order_by(column)
rows = conn.execute(stmt)

Qué hace text() — y qué no hace

text() crea una construcción de SQL textual; no sanea una cadena que ya contiene entrada interpolada. Declara placeholders para los valores y pásalos por separado a Connection.execute() o Session.execute(). La API de expresiones Core de SQLAlchemy enlaza valores literales de Python cuando corresponde, pero los fragmentos textuales siguen siendo sintaxis SQL. Los parámetros no sustituyen nombres de tablas, columnas ni direcciones de orden. Asigna la estructura elegida por el usuario a expresiones SQLAlchemy fijas. Parametrizar previene SQL Injection, pero no sustituye la autorización ni la validación de reglas de negocio.

Cómo auditar el código

rg -n 'text\(|\.execute\(' --glob '*.py' .

Preguntas frecuentes

¿Los constructores de consultas Core y ORM de SQLAlchemy son siempre seguros?

Enlazan valores de Python en construcciones normales, pero la seguridad depende de cómo se construya la sentencia. Revisa SQL textual, construcciones SQL literales e identificadores dinámicos. Ninguna API vuelve segura una cadena SQL tras concatenarle entradas.

Referencias

Véase también Inyección SQL (CWE-89): cómo funciona y cómo evitarla en cada lenguaje — flawopen.com ¿La verificación de consultas de sqlx en compilación evita la inyección SQL? ¿Los procedimientos almacenados evitan la inyección SQL? ¿El QueryBuilder de TypeORM es seguro frente a SQL Injection? Django ORM y SQL Injection: patrones seguros Inyección SQL en Doctrine ORM: consultas seguras EF Core FromSqlRaw: SQL parametrizado seguro