flawopen.com/SQL Injection/Is an ORM enough?
Is using an ORM enough to prevent SQL injection?
An ORM is like a kitchen that prepares orders from a form: its normal query builder keeps values separate. A raw-SQL shortcut is another entrance with its own rules. Check the exact API before trusting interpolated values.
var sql = $"SELECT * FROM dbo.Blogs WHERE Url = '{url}'";
var rows = await context.Blogs
.FromSqlRaw(sql)
.ToListAsync();
// User text is inserted into SQL before execution.
var rows = await context.Blogs
.FromSql($"SELECT * FROM dbo.Blogs WHERE Url = {url}")
.ToListAsync();
// EF Core 7+: interpolation becomes a SQL parameter.
How these APIs handle values
ORM query builders and raw-SQL APIs are not one uniform security boundary. Official docs describe safe value binding in Django raw(sql, params), SQLAlchemy text() with separate execution parameters, Rails placeholder conditions, EF Core FromSql (7+) / FromSqlInterpolated, GORM Raw(sql, args...), and Prisma tagged $queryRaw. Raw APIs differ: EF Core FromSqlRaw is safe with separately supplied parameters but unsafe when user text is inserted into its SQL string; Prisma $queryRawUnsafe can bind values separately, but concatenated untrusted text remains unsafe. A method name alone does not establish how a call handles values. Bind every data value using that API's documented mechanism. SQL identifiers and query structure cannot be bound as values; select them from a fixed application-owned allowlist. The framework guides below show specific contracts.
What "enough" actually requires
- ✓Use the ORM query builder for ordinary values and filters.
- ✓For raw SQL, bind every data value with the API’s documented parameter mechanism.
- ✓Choose dynamic identifiers from fixed application-owned allowlists; parameters cannot bind SQL structure.
- ✓Review raw-query calls for string concatenation, interpolation, and unsafe method variants.
FAQ
No. Some raw-SQL APIs bind separately supplied values, and some safe APIs accept interpolated values as parameters. EF Core 7+ FromSql accepts an interpolated FormattableString, while FromSqlRaw needs values supplied separately; Prisma $queryRawUnsafe can also bind values but does not sanitize SQL text you construct. Verify the exact method contract and keep untrusted values out of SQL structure.
References
- Django SQL queries
- SQLAlchemy DBAPI
- Rails Active Record
- EF Core SQL queries
- GORM Security
- Prisma raw queries
- Django guide
- SQLAlchemy guide
- Rails guide
- EF Core guide
- GORM guide
- Prisma guide