C# and .NET secure coding¶
C# applications can expose injection, authorization and configuration weaknesses even when their types compile correctly. This guide uses ASP.NET Core, Microsoft.Data.SqlClient and SQL Server to show how an untrusted search value reaches a database safely. Adapt the connection lifecycle and error handling to your application.
Bind query values¶
Assume connection is an open SqlConnection and name is an untrusted, length-validated string. The examples run inside an async method; import Microsoft.Data.SqlClient and System.Data.
Unsafe: SQL and data share one string.
using var command = new SqlCommand(
"SELECT Id FROM Customers WHERE Name = '" + name + "'",
connection);
using var reader = await command.ExecuteReaderAsync();
Safer: keep the SQL fixed and bind the value.
using var command = new SqlCommand(
"SELECT Id FROM Customers WHERE Name = @name", connection);
command.Parameters.Add("@name", SqlDbType.NVarChar, 100).Value = name;
using var reader = await command.ExecuteReaderAsync();
The parameter is data rather than additional SQL syntax. Its type and length should match the database column. Reject oversized input before executing the command; do not silently truncate a customer identifier. Microsoft's SqlParameter documentation describes the API.
Parameters do not choose table names, sort directions or authorization policy. Map a requested sort key to a fixed server-owned expression, and scope customer records to the authenticated tenant separately. Raw SQL APIs in an ORM need the same review.
Check the fix¶
In an isolated test database, create customers named O'Reilly and Northwind Demo. Searching for the first must return only its own row without a syntax error. Repeat the request as a user from another tenant and verify the application's ownership check denies access. No production data is needed.
Also review Razor output escaping, deserialization entry points, TLS callbacks and secrets in configuration. Start with SQL injection, XSS and insecure deserialization. OWASP's SQL guidance explains parameterization and least privilege.
These are source review examples. Available scanner checks depend on the installed version, framework and configuration; a clean result does not replace testing the authorization boundary.