FlawOpen

flawopen.com/SQL Injection/Is an ORM enough?

Is using an ORM enough to prevent SQL injection?

Reference page
Short answer

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.

UNSAFE — user text inside FromSqlRaw SQL
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.
SAFE — bind interpolation with FromSql (EF Core 7+)
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

FAQ

Are raw SQL methods always unsafe?

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

See also SQL Injection (CWE-89): How It Works and How to Prevent It in Every Language — flawopen.com Is Knex.js Safe from SQL Injection? MyBatis ${} vs #{}: Prevent SQL Injection MySQLi vs PDO: Secure Prepared Statements Is NHibernate Safe from SQL Injection? MongoDB NoSQL Injection: Safe Query Filters Why String Formatting Risks Numeric ID Queries