Merge pull request #21265 from github/redsun82/csharp-csrf-inheritance

C#: Fix CSRF query to check antiforgery attributes on base classes
This commit is contained in:
Paolo Tranquilli
2026-02-05 14:20:30 +01:00
committed by GitHub
6 changed files with 70 additions and 2 deletions

View File

@@ -54,12 +54,12 @@ predicate hasGlobalAntiForgeryFilter() {
predicate isUnvalidatedPostMethod(Class c, Method m) {
c.(Controller).getAPostActionMethod() = m and
not m.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and
not c.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute
not c.getABaseType*().getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute
or
c.(AspNetCore::MicrosoftAspNetCoreMvcController).getAnActionMethod() = m and
m.getAnAttribute() instanceof AspNetCore::MicrosoftAspNetCoreMvcHttpPostAttribute and
not m.getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute and
not c.getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute
not c.getABaseType*().getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute
}
Element getAValidatedElement() {

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* The `cs/web/missing-token-validation` ("Missing cross-site request forgery token validation") query now recognizes antiforgery attributes on base controller classes, fixing false positives when `[ValidateAntiForgeryToken]` or `[AutoValidateAntiforgeryToken]` is applied to a parent class.

View File

@@ -29,3 +29,34 @@ public class HomeController : Controller
{
}
}
// GOOD: Base class has AutoValidateAntiforgeryToken attribute
[AutoValidateAntiforgeryToken]
public abstract class BaseController : Controller
{
}
public class DerivedController : BaseController
{
// GOOD: Inherits antiforgery validation from base class
[HttpPost]
public ActionResult InheritedValidation()
{
return View();
}
}
// BAD: Base class without antiforgery attribute
public abstract class UnprotectedBaseController : Controller
{
}
public class DerivedUnprotectedController : UnprotectedBaseController
{
// BAD: No antiforgery validation on this or any base class
[HttpPost]
public ActionResult NoInheritedValidation()
{
return View();
}
}

View File

@@ -1 +1,2 @@
| MissingAntiForgeryTokenValidation.cs:7:25:7:29 | Login | Method 'Login' handles a POST request without performing CSRF token validation. |
| MissingAntiForgeryTokenValidation.cs:58:25:58:45 | NoInheritedValidation | Method 'NoInheritedValidation' handles a POST request without performing CSRF token validation. |

View File

@@ -29,3 +29,34 @@ public class HomeController : Controller
{
}
}
// GOOD: Base class has ValidateAntiForgeryToken attribute
[ValidateAntiForgeryToken]
public abstract class BaseController : Controller
{
}
public class DerivedController : BaseController
{
// GOOD: Inherits antiforgery validation from base class
[HttpPost]
public ActionResult InheritedValidation()
{
return View();
}
}
// BAD: Base class without antiforgery attribute
public abstract class UnprotectedBaseController : Controller
{
}
public class DerivedUnprotectedController : UnprotectedBaseController
{
// BAD: No antiforgery validation on this or any base class
[HttpPost]
public ActionResult NoInheritedValidation()
{
return View();
}
}

View File

@@ -1 +1,2 @@
| MissingAntiForgeryTokenValidation.cs:7:25:7:29 | Login | Method 'Login' handles a POST request without performing CSRF token validation. |
| MissingAntiForgeryTokenValidation.cs:58:25:58:45 | NoInheritedValidation | Method 'NoInheritedValidation' handles a POST request without performing CSRF token validation. |