FlawOpen

flawopen.com/Inyección SQL en Rust/sqlx

¿La verificación de consultas de sqlx en compilación evita la inyección SQL?

Página de referencia
Respuesta breve

query! valida una consulta literal frente al esquema real de la base de datos durante la compilación; no vuelve segura retroactivamente una consulta construida dinámicamente. Mantén los valores separados del SQL mediante parámetros enlazados.

INSEGURO — interpolar entrada en SQL
let user_id: String = read_user_input();
let q = format!(
  "SELECT id FROM users WHERE id = '{}'",
  user_id
);
// Representative only: data and SQL syntax are mixed.
// Never pass user-influenced SQL as AssertSqlSafe.
SEGURO — enlazar valor con query!
let user_id: &str = read_user_input();
// PostgreSQL; query! checks the configured schema.
sqlx::query!(
  "SELECT id FROM users WHERE id = $1",
  user_id
).fetch_one(&pool).await?

Qué valida realmente la comprobación en compilación

La macro query! de SQLx 0.9 exige una cadena literal y comprueba la sintaxis, los tipos de parámetros y los tipos del resultado frente al esquema de base de datos configurado durante la compilación; configura DATABASE_URL o metadatos offline versionados. Este ejemplo es específico de PostgreSQL: el marcador es $1. SQLx recomienda $1 para PostgreSQL y SQLite; MySQL y MariaDB usan marcadores posicionales ?. La función de ejecución query() puede enlazar valores con .bind() cuando la estructura SQL es fija o está controlada por la aplicación. En SQLx 0.9, pasar una cadena dinámica requiere AssertSqlSafe; ese tipo solo afirma que la consulta es segura, no sanea la cadena. Nunca lo uses para validar una cadena con valores no confiables interpolados.

Cómo revisar tu base de código

rg -n 'format!\s*\(|sqlx::query(_as)?\s*\(' --glob '*.rs'

Preguntas frecuentes

¿Debo usar siempre la macro query! en vez de query()?

Prefiere query! cuando los requisitos de consulta literal y esquema disponible en compilación encajen con tu proyecto; añade comprobaciones de SQL y tipos. La consulta dinámica query() también es segura si enlazas todos los valores con .bind(). En ambos casos, nunca interpolas datos no confiables en la sintaxis SQL.

Referencias

Véase también Inyección SQL (CWE-89): cómo funciona y cómo evitarla en cada lenguaje — flawopen.com ¿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 FastAPI y SQL Injection: qué protege Pydantic