CA5391: Use antiforgery tokens in ASP.NET Core MVC controllers
Property | Value |
---|---|
Rule ID | CA5391 |
Title | Use antiforgery tokens in ASP.NET Core MVC controllers |
Category | Security |
Fix is breaking or non-breaking | Non-breaking |
Enabled by default in .NET 9 | No |
Cause
Actions that result in modifying operations don't have an antiforgery token attribute. Or, using a global antiforgery token filter without calling expected anti forgery token functions.
Rule description
Handling a POST
, PUT
, PATCH
, or DELETE
request without validating an antiforgery token may be vulnerable to cross-site request forgery attacks. A cross-site request forgery attack can send malicious requests from an authenticated user to your ASP.NET Core MVC controller.
How to fix violations
- Mark the modifying action with a valid antiforgery token attribute:
- Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute.
- Attribute whose name is like
%Validate%Anti_orgery%Attribute
.
- Add the valid forgery token attribute into the global filter with Microsoft.AspNetCore.Mvc.Filters.FilterCollection.Add.
- Add any custom or Mvc-provided antiforgery filter class that calls
Validate
on any class that implements the Microsoft.AspNetCore.Antiforgery.IAntiforgery interface.
When to suppress warnings
It's safe to suppress this rule if solutions other than using antiforgery token attributes are adopted to mitigate CSRF vulnerabilities. For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core.
Suppress a warning
If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
#pragma warning disable CA5391
// The code that's violating the rule is on this line.
#pragma warning restore CA5391
To disable the rule for a file, folder, or project, set its severity to none
in the configuration file.
[*.{cs,vb}]
dotnet_diagnostic.CA5391.severity = none
For more information, see How to suppress code analysis warnings.
Configure code to analyze
You can configure whether the rule applies only to derived classes of Microsoft.AspNetCore.Mvc.Controller in your codebase. For example, to specify that the rule should not run on any code within derived types of ControllerBase, add the following key-value pair to an .editorconfig file in your project:
dotnet_code_quality.CA5391.exclude_aspnet_core_mvc_controllerbase = true
Pseudo-code examples
Without anti forgery token attribute violation
using Microsoft.AspNetCore.Mvc;
class ExampleController : Controller
{
[HttpDelete]
public IActionResult ExampleAction (string actionName)
{
return null;
}
[ValidateAntiForgeryToken]
[HttpDelete]
public IActionResult AnotherAction (string actionName)
{
return null;
}
}
Without valid global anti forgery filter
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
class ExampleController : Controller
{
[ValidateAntiForgeryToken]
[HttpDelete]
public IActionResult AnotherAction (string actionName)
{
return null;
}
[HttpDelete]
public IActionResult ExampleAction (string actionName)
{
return null;
}
}
class FilterClass : IAsyncAuthorizationFilter
{
public Task OnAuthorizationAsync (AuthorizationFilterContext context)
{
return null;
}
}
class BlahClass
{
public static void BlahMethod ()
{
FilterCollection filterCollection = new FilterCollection ();
filterCollection.Add(typeof(FilterClass));
}
}
Marked with an anti forgery token attribute solution
using Microsoft.AspNetCore.Mvc;
class ExampleController : Controller
{
[ValidateAntiForgeryToken]
[HttpDelete]
public IActionResult ExampleAction ()
{
return null;
}
[ValidateAntiForgeryToken]
[HttpDelete]
public IActionResult AnotherAction ()
{
return null;
}
}
Using a valid global anti forgery filter
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
class ExampleController : Controller
{
[ValidateAntiForgeryToken]
[HttpDelete]
public IActionResult AnotherAction()
{
return null;
}
[HttpDelete]
public IActionResult ExampleAction()
{
return null;
}
}
class FilterClass : IAsyncAuthorizationFilter
{
private readonly IAntiforgery antiforgery;
public FilterClass(IAntiforgery antiforgery)
{
this.antiforgery = antiforgery;
}
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
return antiforgery.ValidateRequestAsync(context.HttpContext);
}
}
class BlahClass
{
public static void BlahMethod()
{
FilterCollection filterCollection = new FilterCollection();
filterCollection.Add(typeof(FilterClass));
}
}