Security checklist for C#/.NET backend (ASP.NET Core, EF Core, Event Sourcing). Covers secrets management, input validation, SQL injection, authentication, authorization, rate limiting, security headers, sensitive data handling, Problem Details (RFC 7807), and event sourcing security. Invoked via /dev-security (unified entry point) — not directly.
Installation
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
var connectionString = "Server=prod-db;Password=secret123";
var apiKey = "sk-proj-xxxxx";
Always do this
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
var apiKey = builder.Configuration["ExternalApi:Key"];
// Verify at startupif (string.IsNullOrEmpty(apiKey))
thrownew InvalidOperationException("ExternalApi:Key not configured");
Azure Key Vault (Production)
// Azure Key Vault integration
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{vaultName}.vault.azure.net/"),
new DefaultAzureCredential());
Checklist:
No hardcoded connection strings, API keys, or passwords
Secrets in User Secrets (dev), Azure Key Vault / env vars (prod)
Azure Key Vault configured for production deployments
appsettings.Development.json in .gitignore
No secrets in git history (git log -p -S "password")
### File Upload Validation
```csharp
[HttpPost("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file.Length > 5 * 1024 * 1024)
return BadRequest("File too large (max 5MB)");
var allowedTypes = new[] { "image/jpeg", "image/png", "application/pdf" };
if (!allowedTypes.Contains(file.ContentType))
return BadRequest("Invalid file type");
var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!new[] { ".jpg", ".jpeg", ".png", ".pdf" }.Contains(ext))
return BadRequest("Invalid extension");
// Use a generated filename, never the user-provided one
var safeName = $"{Guid.NewGuid()}{ext}";
// ...
}
Checklist:
All API inputs validated with Result-based validation (Results) or DataAnnotations
File uploads restricted (size, type, extension)
Never trust client-side validation alone — always validate server-side
Error messages don't leak internal details
3. SQL Injection Prevention
Note: If using Event Sourcing (e.g., EventSourcing with Azure Blob Storage),
SQL injection is not applicable. Focus on blob key validation and event stream access control instead.
Never do this
var sql = $"SELECT * FROM Users WHERE Email = '{email}'";
await context.Database.ExecuteSqlRawAsync(sql);
Always do this
// EF Core — parameterized automaticallyvar user = await context.Users.FirstOrDefaultAsync(u => u.Email == email);
// If raw SQL is needed — parameterizedawait context.Database.ExecuteSqlInterpolatedAsync(
$"SELECT * FROM Users WHERE Email = {email}");
// Or explicit parametersawait context.Database.ExecuteSqlRawAsync(
"SELECT * FROM Users WHERE Email = @p0", email);
Checklist:
All queries use EF Core LINQ or parameterized SQL
No string concatenation in any SQL
ExecuteSqlInterpolatedAsync over ExecuteSqlRawAsync
For Event Sourcing: blob keys validated and sanitized
For Event Sourcing: event stream access scoped per tenant/user
4. Authentication & Authorization
// Enforce auth on endpoints
app.MapGet("/api/orders", GetOrders).RequireAuthorization();
// Role-based
app.MapDelete("/api/orders/{id}", DeleteOrder).RequireAuthorization("AdminOnly");
// Policy-based authorization
builder.Services.AddAuthorizationBuilder()
.AddPolicy("AdminOnly", p => p.RequireRole("Admin"))
.AddPolicy("CanManageOrders", p => p.RequireClaim("permission", "orders:manage"));
Scan for responses that leak stack traces, internal paths, or sensitive data in error messages. Production APIs should return Problem Details (RFC 7807) without internal details.
Step 2 — Check for auth failures in logs:
Filter structured logs for 401/403 responses. A high volume may indicate misconfigured auth, missing policies, or endpoints that should require auth but don't.