Join our Newsletter — 33% off our NHI Course
Home› FAQ› Cyber Security› Why does raw SQL in EF Core create…
Cyber Security

Why does raw SQL in EF Core create more injection risk than LINQ queries?

← Back to all FAQ
By NHI Mgmt Group Editorial Team Updated September 25, 2026 Domain: Cyber Security

LINQ usually produces parameterized SQL, which keeps user input separate from the query structure. Raw SQL is riskier because developers may concatenate or interpolate untrusted input directly into the statement. When that happens, the database can interpret attacker-controlled text as executable SQL, so teams should parameterize inputs or validate them against a strict allow-list first.

Why raw SQL creates a different injection boundary than LINQ

EF Core is not insecure by default, but it gives you two very different paths into the database engine. LINQ goes through EF Core’s query translation layer, which separates values from query structure and usually sends parameters instead of stitched-together text. Raw SQL skips that protection layer, so the security of the final statement depends much more on how the developer builds the string.

That difference matters because sql injection is not just “bad input,” it is a failure to preserve the boundary between code and data. With LINQ, user-supplied values typically remain values. With raw SQL, any untrusted fragment that reaches string concatenation or interpolation can change the meaning of the statement itself, including filters, ordering, joins, or even additional commands where the provider permits them.

This is why the risk is not simply that raw SQL exists, but that it makes unsafe composition easier to express and harder to notice in review. A query can look harmless in code while still embedding untrusted text into a clause that the database will execute as logic. The safest pattern is to use raw SQL only when you need it, and to keep all user-controlled data parameterized or tightly allow-listed.

Where LINQ lowers exposure and where it still needs care

LINQ reduces injection risk because EF Core can translate expression trees into SQL with parameter placeholders, so the database receives the variable content separately from the statement structure. That means a search term, identifier, or date filter is normally treated as data rather than executable syntax. For ordinary query shapes, this is the main reason LINQ is preferred over hand-written SQL for untrusted input.

Even so, LINQ is not a magic shield. The security benefit depends on keeping the query inside EF Core’s normal translation path and not falling back into dynamic string construction for fragments such as raw predicates, dynamic ordering, or SQL snippets. Once a developer starts building those fragments from user input, the same injection problem can return, even if the outer query began as LINQ.

In practice, LINQ is safer because it makes the secure pattern the default. Raw SQL demands that developers consciously preserve that pattern themselves. For teams reviewing application code, the key question is whether user input is reaching a query as a parameter or as part of the SQL text. That review point is more useful than assuming every raw query is unsafe or every LINQ query is automatically safe.

Safe use of raw SQL in EF Core when you actually need it

Raw SQL is justified when you need a database-specific feature, a complex query shape, or a performance-sensitive statement that LINQ cannot express cleanly. The important discipline is to treat the SQL text as code and every external value as untrusted until it has been safely constrained. This is especially important for clauses that cannot always be parameterized cleanly, such as dynamic table names, column names, or sort direction.

When the value is meant to be data, pass it as a parameter through EF Core’s parameter APIs or through an interpolated form that still binds parameters rather than concatenating strings. When the value is meant to control structure, do not pass it through directly; use a strict allow-list of known-safe options and map user choice to a fixed SQL fragment. That distinction is the core control.

For review purposes, raw SQL should be treated as a higher-risk code path. It deserves targeted testing, secure code review, and careful handling of any input that crosses from request data into the query. A query that seems harmless in a development environment can become injectable the moment a future change introduces concatenation, so the safe pattern has to be consistent, not occasional.

Risk and Threat Considerations

Raw SQL expands the attack surface because it can turn routine request parameters into direct database commands if developers interpolate them into the statement. The main risk is not the use of SQL itself, but the loss of separation between user-controlled data and executable query structure, which can lead to data exposure, unauthorized modification, or broader database compromise.

Failure mechanism: An attacker supplies input that alters the intended SQL syntax when the application concatenates or otherwise embeds that input into the query text, allowing the database to interpret it as part of the command rather than as a value.

Impact: Depending on the database permissions and query context, this can expose sensitive records, bypass application logic, modify or delete data, and in some environments provide a foothold for deeper compromise through the database account’s privileges.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP ASVS, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
OWASP ASVSV8 — AuthorizationInjection can bypass intended query logic and access boundaries.
V15 — Secure Coding and ArchitectureThe issue is unsafe construction of database queries in application code.
Recommendation — Verify query inputs cannot alter authorization-relevant SQL structure. Build database access paths to keep values separate from SQL text.
NIST SP 800-53 Rev 5SI-10 — Information Input ValidationUntrusted input must be constrained before it reaches a query parser.
AC-6 — Least PrivilegeInjected SQL is limited or amplified by the database account’s privileges.
Recommendation — Validate and constrain externally sourced values before using them in SQL. Limit database account privileges to reduce injection blast radius.
CIS Controls v8CIS-16 — Application Software SecurityThe question concerns secure coding practices for database access.
Recommendation — Review data-access code for parameterization and unsafe query construction.

Practitioner Guidance

What to verify: Check every raw SQL call site for the exact point where user input enters the statement. If the value can affect a WHERE clause, ORDER BY clause, join condition, or identifier, confirm whether it is parameterized or restricted to an allow-list before the code is considered safe.

Common mistake: Treating interpolated strings as acceptable because the query “works” or because the input is “internal.” Internal data is still untrusted if it originates from a request, file, queue, or upstream service that a user can influence.

Practitioner takeaway: Use LINQ when it expresses the query cleanly, and when raw SQL is necessary, separate data from syntax with parameters or strict allow-lists; that boundary is what determines whether the query is merely dynamic or actually injectable.

Deepen Your Knowledge

Sign up to our weekly newsletter — get 33% off our NHI Foundation Level Course

    NHIMG Editorial Note
    Reviewed and updated by the NHIMG editorial team on September 25, 2026.
    NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org