FlawOpen

flawopen.com/SQL Injection in Rust/sqlx

Does sqlx's compile-time query checking prevent SQL injection?

Reference page
Short answer

query! checks a literal query against a database schema at build time; it does not retroactively make a dynamically assembled query safe. Keep values separate from SQL with bind parameters.

UNSAFE — interpolate input into 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.
SAFE — bind a value with 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?

What the compile-time check actually validates

SQLx 0.9's query! macro requires a string literal and checks syntax, bind types, and result types against the configured database schema at build time; configure DATABASE_URL or checked-in offline metadata. This code pair is specifically PostgreSQL: its placeholder is $1. SQLx recommends $1 for PostgreSQL and SQLite; MySQL and MariaDB use positional ? placeholders. Runtime query() can bind values with .bind() when the SQL structure is fixed or application-controlled. In SQLx 0.9, passing a dynamic string requires AssertSqlSafe; that type is only an assertion, not a sanitizer. Never use it to bless a string containing untrusted interpolated values.

How to check your codebase

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

FAQ

Should I always use the query! macro over query()?

Use query! when its literal-query and build-time schema requirements fit your project; it adds compile-time SQL and type checking. Dynamic query() is also safe when you bind every value with .bind(). In both cases, never interpolate untrusted data into SQL syntax.

References

See also SQL Injection (CWE-89): How It Works and How to Prevent It in Every Language — flawopen.com Are Stored Procedures Immune to SQL Injection? Is TypeORM QueryBuilder Safe from SQL Injection? Django ORM SQL Injection: Safe Patterns and Pitfalls Doctrine ORM SQL Injection: Safe Queries and Pitfalls EF Core FromSqlRaw: Safe Parameterized SQL FastAPI SQL Injection: What Pydantic Does and Doesn’t Stop