FlawOpen

flawopen.com/Injeção de SQL em Rust/sqlx

A verificação de consultas do sqlx em compilação evita SQL injection?

Página de referência
Resposta curta

query! verifica uma consulta literal com o esquema do banco durante a compilação; isso não torna segura, retroativamente, uma consulta montada dinamicamente. Mantenha os valores separados do SQL usando parâmetros vinculados.

INSEGURO — interpolar entrada no 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 — vincular valor com 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?

O que a verificação em compilação realmente valida

A macro query! do SQLx 0.9 exige uma string literal e verifica a sintaxe, os tipos dos parâmetros e os tipos do resultado em relação ao esquema configurado do banco durante a compilação; configure DATABASE_URL ou metadados offline versionados. Este exemplo usa PostgreSQL: o placeholder é $1. O SQLx recomenda $1 para PostgreSQL e SQLite; MySQL e MariaDB usam placeholders posicionais ?. A função query() em tempo de execução pode vincular valores com .bind() quando a estrutura SQL é fixa ou controlada pela aplicação. No SQLx 0.9, passar uma string dinâmica exige AssertSqlSafe; esse tipo apenas declara que a consulta é segura, não sanitiza a string. Nunca o use para aprovar uma string com valores não confiáveis interpolados.

Como verificar sua base de código

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

Perguntas frequentes

Devo sempre preferir a macro query! a query()?

Prefira query! quando os requisitos de consulta literal e esquema disponível na compilação se encaixarem no projeto; ela adiciona verificações de SQL e tipos. A consulta dinâmica query() também é segura quando todos os valores são vinculados com .bind(). Em ambos os casos, nunca interpole dados não confiáveis na sintaxe SQL.

Referências

Veja também SQL Injection (CWE-89): como funciona e como evitar em todas as linguagens — flawopen.com Procedimentos armazenados evitam SQL injection? O QueryBuilder do TypeORM é seguro contra SQL Injection? Django ORM e SQL Injection: padrões seguros Injeção SQL no Doctrine ORM: consultas seguras EF Core FromSqlRaw: SQL parametrizado seguro FastAPI e SQL Injection: o que o Pydantic protege