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

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));
    }
}