Learn C# - Secure Coding & Best Practices
Series/Learn C#/Episode 13
Episode 13 of 23

Learn C# - Secure Coding & Best Practices

This episode covers secure programming practices: input validation with DataAnnotations, preventing OWASP Top 10 attacks in .NET applications, secure storage with the Data Protection API, and preventing SQL injection, XSS, CSRF, and sensitive data leakage.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Security isn't a feature added at the end — it's a way of thinking embedded in every line of code. Most successful attacks exploit vulnerabilities that were actually easy to prevent from the start.

In episode 12 you secured access. Episode 13 goes deeper: how to write code that has no vulnerabilities from the outset. This covers input validation, safe practices against the OWASP Top 10, storing sensitive data, and preventing the most common web attacks.

Input Validation and Sanitization

Validation with DataAnnotations

The first golden rule: never trust user input. ASP.NET Core validates models automatically if you declare the rules with DataAnnotations:

Model validation
public class DaftarRequest
{
    [Required]
    [EmailAddress]
    public string Email { get; set; } = "";
 
    [Required]
    [StringLength(128, MinimumLength = 8)]
    public string Password { get; set; } = "";
 
    [Range(0, 150)]
    public int Umur { get; set; }
}

Because the controller is decorated with [ApiController], requests that fail validation are automatically rejected with status 400 before the method runs. This server-side validation is mandatory — browser-side validation is only for convenience, not security.

OWASP Top 10 for .NET Applications

The Main Threat Map

The OWASP Top 10 is a periodically updated list of the biggest web security risks. For .NET applications, pay attention to the most relevant ones:

  • Broken Access Control: check authorization on every endpoint, not just in the UI.
  • Cryptographic Failures: don't store passwords or tokens without encryption.
  • Injection: always use parameterized queries and escape input.
  • Security Misconfiguration: disable error details in production, hide version headers.
  • SSRF: restrict the target URLs your server can request internally.

Most of the points above are already handled by the framework if you follow the right patterns, but regular audits are still necessary. Beyond that, many vulnerabilities come not from the framework but from developers assuming input will always behave well — an assumption that should always be questioned.

Secure Storage with the Data Protection API

Protecting Sensitive Data

ASP.NET Core provides the Data Protection API for encrypting data such as cookies and tokens. Data is sealed in a key ring with keys that can be rotated:

Data Protection API
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo("/var/lib/toko/keys"))
    .SetApplicationName("Toko");
 
var app = builder.Build();
 
var protector = app.Services.GetRequiredService<IDataProtectionProvider>()
    .CreateProtector("PesanSensitif");
var ciphertext = protector.Protect("data rahasia");
Console.WriteLine(ciphertext);

CreateProtector("PesanSensitif") produces encrypted data that can only be opened by an application with the same key ring. The key ring is persisted to the filesystem so it survives restarts — this is what ASP.NET Core uses to protect authentication cookies.

Important: the Data Protection API is not a replacement for encrypting long-lived data such as passwords or credit cards. For data that must persist and be opened by other applications, use standard symmetric encryption techniques like AES. Data Protection is intended for temporary data understood only by the application itself.

Besides encrypting data, make sure your development communication channel is also secure. The local HTTPS certificate can be enabled and trusted with dotnet dev-certs https --trust; this command marks the development certificate as trusted so browsers no longer show warnings. In production, certificates are managed separately by the platform where the app is deployed, but the habit of securing this channel matters in every environment.

Preventing Injection, XSS, CSRF, and Data Leakage

SQL Injection and Raw SQL

SQL injection happens when user input is concatenated raw into a query. In EF Core, always use parameterized:

Safe and unsafe queries
var aman = await db.Produk
    .FromSqlInterpolated($"SELECT * FROM Produk WHERE Nama = {input}")
    .ToListAsync();
 
var buruk = $"SELECT * FROM Produk WHERE Nama = '{input}'";

FromSqlInterpolated turns interpolation into safe SQL parameters. Building query strings manually, like the buruk example, opens an injection hole — if the input contains '; DROP TABLE Produk;--, your query can be abused.

XSS, CSRF, and Razor Protection

Razor Pages and MVC escape HTML output automatically, so XSS is avoided as long as you don't use @Html.Raw without reason. For CSRF, the framework provides anti-forgery tokens that must be included in forms and in requests that change state:

Anti-forgery token
builder.Services.AddAntiforgery(o => o.HeaderName = "X-CSRF-TOKEN");

Meanwhile, make sure sensitive data doesn't leak: don't log passwords or tokens, and use environment variables for secrets instead of hardcoding them. You already learned how to store secrets safely in episode 8.

Closing

Key takeaways:

  • Server-side input validation is mandatory, not just browser-side.
  • The OWASP Top 10 is an audit checklist that should be run regularly.
  • The Data Protection API encrypts cookies and sensitive data with a key ring.
  • Always use parameterized queries to prevent SQL injection.
  • Razor escapes output automatically; anti-forgery tokens prevent CSRF.

In the next episode 14 we unleash the full power of the processor: asynchronous programming and concurrency — the Task-based async pattern, Parallel LINQ and the Task Parallel Library, Channel and async streams, and synchronization primitives and thread safety.

Learn C# - Secure Coding & Best Practices | Learn C#