dotnet-security-owasp
Securing .NET code or reviewing for vulnerabilities. OWASP Top 10 mitigations, pattern warnings.
What this skill does
# dotnet-security-owasp
OWASP Top 10 (2021) security guidance for .NET applications. Each category includes the vulnerability description, .NET-specific risk, mitigation code examples, and common pitfalls. This skill is the canonical owner of deprecated security pattern warnings (CAS, APTCA, .NET Remoting, DCOM, BinaryFormatter).
**Out of scope:** Authentication/authorization implementation -- API-level auth patterns (Identity, OAuth/OIDC, JWT, passkeys, CORS) -- see [skill:dotnet-api-security]. Blazor auth UI (AuthorizeView, CascadingAuthenticationState) -- see [skill:dotnet-blazor-auth]. Cloud-specific security services (Azure Key Vault, AWS Secrets Manager) -- cloud epics. Cryptographic algorithm selection and key management -- see [skill:dotnet-cryptography]. Configuration binding and Options pattern -- see [skill:dotnet-csharp-configuration].
Cross-references: [skill:dotnet-secrets-management] for secrets handling, [skill:dotnet-cryptography] for cryptographic best practices, [skill:dotnet-csharp-coding-standards] for secure coding conventions.
---
## A01: Broken Access Control
**Vulnerability:** Users act outside their intended permissions -- accessing other users' data, elevating privileges, or bypassing access checks.
**Risk in .NET:** Missing `[Authorize]` attributes on controllers/endpoints, insecure direct object references (IDOR) where user IDs are taken from route parameters without ownership validation, and CORS misconfiguration allowing unintended origins.
### Mitigation
```csharp
// 1. Apply authorization globally, then opt out explicitly
builder.Services.AddAuthorizationBuilder()
.SetFallbackPolicy(new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build());
var app = builder.Build();
app.MapControllers(); // All endpoints require auth by default
// 2. Resource-based authorization to prevent IDOR
public sealed class DocumentAuthorizationHandler
: AuthorizationHandler<EditRequirement, Document>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
EditRequirement requirement,
Document resource)
{
if (resource.OwnerId == context.User.FindFirstValue(ClaimTypes.NameIdentifier))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// In the endpoint:
app.MapPut("/documents/{id}", async (
int id,
DocumentDto dto,
IAuthorizationService authService,
ClaimsPrincipal user,
AppDbContext db) =>
{
var document = await db.Documents.FindAsync(id);
if (document is null) return Results.NotFound();
var authResult = await authService.AuthorizeAsync(user, document, "Edit");
if (!authResult.Succeeded) return Results.Forbid();
document.Title = dto.Title;
await db.SaveChangesAsync();
return Results.NoContent();
});
```
```csharp
// 3. Restrict CORS to known origins
builder.Services.AddCors(options =>
{
options.AddPolicy("Strict", policy =>
{
policy.WithOrigins("https://app.example.com")
.WithMethods("GET", "POST")
.WithHeaders("Content-Type", "Authorization");
});
});
```
**Gotcha:** `AllowAnyOrigin()` combined with `AllowCredentials()` is rejected at runtime by ASP.NET Core, but `SetIsOriginAllowed(_ => true)` with `AllowCredentials()` silently allows all origins -- never use this pattern.
---
## A02: Cryptographic Failures
**Vulnerability:** Sensitive data exposed due to weak or missing encryption -- plaintext storage, deprecated algorithms, or improper key management.
**Risk in .NET:** Using MD5/SHA1 for hashing passwords, storing connection strings with plaintext passwords in `appsettings.json`, transmitting sensitive data over HTTP, or using `DES`/`RC2` for encryption.
### Mitigation
```csharp
// Enforce HTTPS and HSTS
builder.Services.AddHttpsRedirection(options =>
{
options.HttpsPort = 443;
});
var app = builder.Build();
app.UseHsts(); // Strict-Transport-Security header
app.UseHttpsRedirection();
// Never store secrets in appsettings.json -- use user secrets or env vars
// See [skill:dotnet-secrets-management] for proper secrets handling
```
```csharp
// Use Data Protection API for symmetric encryption of application data
public sealed class TokenProtector(IDataProtectionProvider provider)
{
private readonly IDataProtector _protector =
provider.CreateProtector("Tokens.V1");
public string Protect(string plaintext) => _protector.Protect(plaintext);
public string Unprotect(string ciphertext) => _protector.Unprotect(ciphertext);
}
```
See [skill:dotnet-cryptography] for algorithm selection (AES-GCM, RSA, ECDSA) and key derivation.
---
## A03: Injection
**Vulnerability:** Untrusted data sent to an interpreter as part of a command or query -- SQL injection, command injection, LDAP injection, and cross-site scripting (XSS).
**Risk in .NET:** String concatenation in SQL queries, `Process.Start` with unsanitized input, rendering user input as raw HTML in Razor pages.
### Mitigation
```csharp
// SQL injection prevention: always use parameterized queries
// EF Core is parameterized by default via LINQ
var orders = await db.Orders
.Where(o => o.CustomerId == customerId)
.ToListAsync();
// When raw SQL is needed, use parameterized interpolation
var results = await db.Orders
.FromSqlInterpolated($"SELECT * FROM Orders WHERE Status = {status}")
.ToListAsync();
// NEVER concatenate user input into SQL:
// var bad = db.Orders.FromSqlRaw("SELECT * FROM Orders WHERE Status = '" + status + "'");
```
```csharp
// XSS prevention: Razor encodes output by default.
// Use @Html.Raw() ONLY for trusted, pre-sanitized HTML.
// In Minimal APIs, return typed results -- not raw strings:
app.MapGet("/greeting", (string name) =>
Results.Content($"<p>Hello, {HtmlEncoder.Default.Encode(name)}</p>",
"text/html"));
// Command injection prevention: avoid Process.Start with user input.
// If unavoidable, validate against an allowlist:
public static bool IsAllowedTool(string toolName) =>
toolName is "dotnet" or "git" or "nuget";
```
**Gotcha:** `FromSqlRaw` with string concatenation bypasses parameterization. Always use `FromSqlInterpolated` or pass `SqlParameter` objects to `FromSqlRaw`.
---
## A04: Insecure Design
**Vulnerability:** Flaws in design patterns that cannot be fixed by implementation alone -- missing rate limiting, lack of defense in depth, unrestricted resource consumption.
**Risk in .NET:** APIs without rate limiting, unbounded file uploads, missing anti-forgery tokens on state-changing operations.
### Mitigation
```csharp
// Rate limiting with built-in middleware (.NET 7+)
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("api", limiterOptions =>
{
limiterOptions.PermitLimit = 100;
limiterOptions.Window = TimeSpan.FromMinutes(1);
limiterOptions.QueueLimit = 0;
});
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});
var app = builder.Build();
app.UseRateLimiter();
app.MapGet("/api/data", () => Results.Ok("data"))
.RequireRateLimiting("api");
```
```csharp
// Anti-forgery for Minimal APIs (.NET 8+)
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
// Form-bound endpoint: antiforgery validated automatically
app.MapPost("/orders", async ([FromForm] string productId, AppDbContext db) =>
{
var order = new Order { ProductId = productId };
db.Orders.Add(order);
await db.SaveChangesAsync();
return Results.Created($"/orders/{order.Id}", order);
});
// JSON endpoint: opt in explicitly with RequireAntiforgery()
app.MapPost("/api/orders", async (CreateOrderDto dto, AppDbContext db) =>
{
var order = new Order { ProductId = dto.ProductId };
db.Orders.Add(order);
await db.SaveChangesAsync();
return Results.Created($"/api/orders/{order.Id}", order);
}).RequireAntiforgery();
``Related in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.