[C#] Recognize RequireAntiforgeryToken attributes - #22322
Conversation
michaelnebel
left a comment
There was a problem hiding this comment.
Thank you very much for the contribution! We really appreciate all the help we can get on keeping the queries up to date!
I have added a suggestion for a minor re-write of the query logic.
| } | ||
|
|
||
| bindingset[controller, method] | ||
| private predicate hasAspNetCoreAntiForgeryValidation(Class controller, Method method) { |
There was a problem hiding this comment.
Perhaps, we can refactor/encapsulate some of the logic and avoid using the bindingset pragmas.
Maybe the remaining part of the query can look something like:
class MvcControllerPostMethod extends Method {
private Controller controller;
MvcControllerPostMethod() { controller.(Controller).getAPostActionMethod() = this }
predicate hasValidateAntiForgeryAttribute() {
this.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute or
controller.getABaseType*().getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute
}
}
class AspNetCoreControllerPostMethod extends Method {
private AspNetCore::MicrosoftAspNetCoreMvcController controller;
AspNetCoreControllerPostMethod() {
controller.(AspNetCore::MicrosoftAspNetCoreMvcController).getAnActionMethod() = this and
this.getAnAttribute() instanceof AspNetCore::MicrosoftAspNetCoreMvcHttpPostAttribute
}
predicate hasValidateAntiForgeryAttribute() {
this.getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute or
controller.getABaseType*().getAnAttribute() instanceof AspNetCore::ValidateAntiForgeryAttribute
}
predicate hasRequireAntiForgeryAttribute() {
hasAspNetCoreAntiForgeryMiddleware() and
(
getEffectiveRequireAntiforgeryTokenAttributeOnMethod(this).requiresValidation()
or
not exists(getEffectiveRequireAntiforgeryTokenAttributeOnMethod(this)) and
getEffectiveRequireAntiforgeryTokenAttributeOnClass(controller).requiresValidation()
)
}
}
predicate isUnvalidatedAspNetCorePostMethod(AspNetCoreControllerPostMethod m) {
not m.hasValidateAntiForgeryAttribute() and
not m.hasRequireAntiForgeryAttribute()
}
predicate isUnvalidatedMvcPostMethod(MvcControllerPostMethod m) {
not m.hasValidateAntiForgeryAttribute()
}
predicate isUnvalidatedPostMethod(Method m) {
isUnvalidatedMvcPostMethod(m) or
isUnvalidatedAspNetCorePostMethod(m)
}
Element getAValidatedElement() {
any(ValidateAntiForgeryTokenAttribute a).getTarget() = result
or
any(AspNetCore::ValidateAntiForgeryAttribute a).getTarget() = result
or
hasAspNetCoreAntiForgeryMiddleware() and
any(RequireAntiforgeryTokenAttribute a | a.requiresValidation()).getTarget() = result
}
from Method postMethod
where
isUnvalidatedPostMethod(postMethod) and
// Verify that validate anti forgery token attributes are used somewhere within this project, to
// avoid reporting false positives on projects that use an alternative approach to mitigate CSRF
// issues.
exists(getAValidatedElement()) and
// Also ignore cases where a global anti forgery filter is in use.
not hasGlobalAntiForgeryFilter()
select postMethod,
"Method '" + postMethod.getName() +
"' handles a POST request without performing CSRF token validation."There was a problem hiding this comment.
Note that then it is also possible to remove the bindingset pragmas on the get* like predicates.
There was a problem hiding this comment.
Thanks for the suggestion. I’ve applied the refactor and removed the bindingset pragmas.
There was a problem hiding this comment.
Pull request overview
Updates the C# CSRF query to recognize RequireAntiforgeryToken when ASP.NET Core antiforgery middleware is configured.
Changes:
- Models enabled, disabled, inherited, and overridden antiforgery metadata.
- Preserves MVC filter validation behavior.
- Adds middleware-present and middleware-absent regression tests.
Show a summary per file
| File | Description |
|---|---|
require-antiforgery-without-middleware/options |
Configures framework stubs. |
require-antiforgery-without-middleware/MissingAntiForgeryTokenValidation.qlref |
Selects the tested query. |
require-antiforgery-without-middleware/MissingAntiForgeryTokenValidation.expected |
Records the expected alert. |
require-antiforgery-without-middleware/MissingAntiForgeryTokenValidation.cs |
Tests metadata without middleware. |
missing-aspnetcore/MissingAntiForgeryTokenValidation.expected |
Updates expected ASP.NET Core results. |
missing-aspnetcore/MissingAntiForgeryTokenValidation.cs |
Tests metadata variants and inheritance. |
disabled-require-antiforgery/options |
Configures framework stubs. |
disabled-require-antiforgery/MissingAntiForgeryTokenValidation.qlref |
Selects the tested query. |
disabled-require-antiforgery/MissingAntiForgeryTokenValidation.expected |
Records no expected results. |
disabled-require-antiforgery/MissingAntiForgeryTokenValidation.cs |
Tests disabled-only metadata behavior. |
MissingAntiForgeryTokenValidation.ql |
Adds antiforgery metadata and middleware recognition. |
2026-08-09-require-antiforgery-token.md |
Documents the analysis improvement. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 11/12 changed files
- Comments generated: 0
- Review effort level: Balanced
michaelnebel
left a comment
There was a problem hiding this comment.
Really good! Thank you very much for improving the query!
I have started a DCA (test) run - if it doesn't show any problems then we can merge.
Recognize enabled
RequireAntiforgeryTokenattributes whenUseAntiforgery()is configured.This handles inherited attributes, explicit opt-outs, and existing MVC antiforgery filters.
Fixes #22238