.NET / C# source review
When it applies
Reviewing C#/.NET source (ASP.NET Core, MVC, or legacy WebForms). The headline risks are unsafe
deserialization, string-built SQL, XXE, and Razor's raw-output escape hatch.
Why it works
.NET ships powerful-but-dangerous serializers (BinaryFormatter, Json.NET with
TypeNameHandling, LosFormatter/ViewState) that instantiate arbitrary types, and several XML APIs
resolve DTDs by default on older frameworks. Reviews find where these meet untrusted input.
Sinks & patterns (grep, then trace to user input)
- Deserialization:
BinaryFormatter, LosFormatter, SoapFormatter, NetDataContractSerializer,
JsonConvert with TypeNameHandling != None, Js.NET/fastJSON polymorphic types → RCE gadgets.
- SQLi: string-concatenated
SqlCommand/ExecuteReader/FromSqlRaw(EF Core) vs parameters.
- Command exec:
Process.Start with concatenated arguments / UseShellExecute.
- XXE:
XmlDocument/XmlReader/XmlTextReader without DtdProcessing=Prohibit (legacy default
resolves entities); XmlSerializer with a user-controlled type.
- XSS: Razor
@Html.Raw(...), MvcHtmlString, WebForms <%= %> with unencoded input;
Response.Write.
- Other: path traversal via
Path.Combine(root, input), LdapConnection filter injection,
reflection (Type.GetType/Activator.CreateInstance) on input, insecure ViewState (no MAC).
Framework specifics
- ASP.NET Core: model binding over-posting/mass assignment (bind whole entity),
[AllowAnonymous]
on sensitive actions, disabled antiforgery on POST APIs, exposed dev endpoints, open redirect via
Redirect(returnUrl) without Url.IsLocalUrl.
- WebForms: ViewState deserialization (machineKey), event-validation off.
Method
- Run
security-code-scan/CodeQL; treat as leads.
rg 'BinaryFormatter|TypeNameHandling|FromSqlRaw|Html\.Raw|XmlDocument|Process\.Start' → trace to input.
- Check controller
[Authorize]/antiforgery coverage and model-binding scope.
- Confirm with
web-deserialization, web-sqli, web-xxe, web-command-injection.
Gotchas
Json.NET is safe by default — the bug is an explicit TypeNameHandling.All/Auto.
- EF Core parameterises LINQ;
FromSqlRaw/ExecuteSqlRaw with interpolation is where SQLi returns.
- ViewState RCE needs the
machineKey (leaked/weak) — note the precondition.
References
OWASP .NET security cheat sheet; ysoserial.net gadget research; Microsoft secure-coding guidance.
1---2name: code-review-dotnet3description: Security review of .NET / C# code — dangerous sinks and ASP.NET pitfalls. Load when reviewing a C#/.NET codebase/PR, on .cs source in scope, or "review this .NET app". Signals: .csproj/.sln, ASP.NET (Core/MVC/WebForms), BinaryFormatter, SqlCommand, Razor Html.Raw, XmlDocument.4---56# .NET / C# source review78## When it applies9Reviewing C#/.NET source (ASP.NET Core, MVC, or legacy WebForms). The headline risks are unsafe10deserialization, string-built SQL, XXE, and Razor's raw-output escape hatch.1112## Why it works13.NET ships powerful-but-dangerous serializers (`BinaryFormatter`, `Json.NET` with14`TypeNameHandling`, `LosFormatter`/ViewState) that instantiate arbitrary types, and several XML APIs15resolve DTDs by default on older frameworks. Reviews find where these meet untrusted input.1617## Sinks & patterns (grep, then trace to user input)18- **Deserialization**: `BinaryFormatter`, `LosFormatter`, `SoapFormatter`, `NetDataContractSerializer`,19 `JsonConvert` with `TypeNameHandling != None`, `Js.NET`/`fastJSON` polymorphic types → RCE gadgets.20- **SQLi**: string-concatenated `SqlCommand`/`ExecuteReader`/`FromSqlRaw`(EF Core) vs parameters.21- **Command exec**: `Process.Start` with concatenated arguments / `UseShellExecute`.22- **XXE**: `XmlDocument`/`XmlReader`/`XmlTextReader` without `DtdProcessing=Prohibit` (legacy default23 resolves entities); `XmlSerializer` with a user-controlled type.24- **XSS**: Razor `@Html.Raw(...)`, `MvcHtmlString`, WebForms `<%= %>` with unencoded input;25 `Response.Write`.26- **Other**: path traversal via `Path.Combine(root, input)`, `LdapConnection` filter injection,27 reflection (`Type.GetType`/`Activator.CreateInstance`) on input, insecure ViewState (no MAC).2829## Framework specifics30- **ASP.NET Core**: model binding over-posting/mass assignment (bind whole entity), `[AllowAnonymous]`31 on sensitive actions, disabled antiforgery on POST APIs, exposed dev endpoints, open redirect via32 `Redirect(returnUrl)` without `Url.IsLocalUrl`.33- **WebForms**: ViewState deserialization (machineKey), event-validation off.3435## Method361. Run `security-code-scan`/CodeQL; treat as leads.372. `rg 'BinaryFormatter|TypeNameHandling|FromSqlRaw|Html\.Raw|XmlDocument|Process\.Start'` → trace to input.383. Check controller `[Authorize]`/antiforgery coverage and model-binding scope.394. Confirm with `web-deserialization`, `web-sqli`, `web-xxe`, `web-command-injection`.4041## Gotchas42- `Json.NET` is safe by default — the bug is an explicit `TypeNameHandling.All/Auto`.43- EF Core parameterises LINQ; `FromSqlRaw`/`ExecuteSqlRaw` with interpolation is where SQLi returns.44- ViewState RCE needs the `machineKey` (leaked/weak) — note the precondition.4546## References47OWASP .NET security cheat sheet; ysoserial.net gadget research; Microsoft secure-coding guidance.