diff --git a/rules/S6932/S6932.AspNet4x.cs b/rules/S6932/S6932.AspNet4x.cs deleted file mode 100644 index 438c62a53ee..00000000000 --- a/rules/S6932/S6932.AspNet4x.cs +++ /dev/null @@ -1,288 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Net.Http; -using System.Web; -using System.Web.Http; -using System.Web.Mvc; -using System.Web.Mvc.Filters; -using System.Web.Routing; - -// Hints: -// * ApiController: does not expose QueryString or Form directly. The rule does not apply there. See MyApiController test case for details. -// * ControllerBase: does not support model binding, so the rule doesn't applies. -public class TestController : Controller -{ - private readonly string Key = "id"; - public ActionResult Post() - { - _ = Request.Form["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^ - _ = Request.Form.Get("id"); // Noncompliant - // ^^^^ - _ = Request.Form.GetValues("id"); // Noncompliant - // ^^^^ - _ = Request.QueryString["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^^^^^ - _ = Request.QueryString.Get("id"); // Noncompliant - // ^^^^^^^^^^^ - _ = Request.QueryString.GetValues("id"); // Noncompliant - // ^^^^^^^^^^^ - return default; - } - - // Parameterized for "Form", "QueryString" - void NoncompliantKeyVariations() - { - _ = Request.Form[@"key"]; // Noncompliant - _ = Request.Form.Get(@"key"); // Noncompliant - _ = Request.Form.GetValues(@"key"); // Noncompliant - - _ = Request.Form[Key]; // FN: Key is a readonly field with a constant initializer (Requires cross procedure SE) - const string key = "id"; - _ = Request.Form[key]; // Noncompliant - _ = Request.Form.Get(key); // Noncompliant - _ = Request.Form.GetValues(key); // Noncompliant - _ = Request.Form[$"prefix.{key}"]; // Noncompliant - _ = Request.Form.Get($"prefix.{key}"); // Noncompliant - _ = Request.Form.GetValues($"prefix.{key}"); // Noncompliant - string localKey = "id"; - _ = Request.Form[localKey]; // FN (Requires SE) - - _ = Request.Form[name: "id"]; // Noncompliant - _ = Request.Form.Get(name: "id"); // Noncompliant - _ = Request.Form.GetValues(name: "id"); // Noncompliant - } - - // Parameterized: Form, QueryString / Request, HttpContext.Request, Request.RequestContext.HttpContext.Request, ControllerContext.RequestContext.HttpContext.Request - // Implementation: Consider adding a CombinatorialDataAttribute https://stackoverflow.com/a/75531690 - void Compliant(string key) - { - // Compliant: Accessing by index is not supported by model binding - _ = Request.Form[0]; - _ = Request.Form.Get(0); - _ = Request.Form.GetValues(0); - // Compliant: Key is not a compile time constant - _ = Request.Form[key]; - _ = Request.Form.Get(key); - _ = Request.Form.GetValues(key); - - _ = Request.Form.AllKeys; - _ = Request.Form.Count; - _ = Request.Form.Keys; - _ = Request.Form.HasKeys(); - _ = Request.Form.GetKey(0); - Request.Form.Set("id", "value"); - Request.Form.Add("id", "value"); - Request.Form.Remove("id"); - _ = Request["id"]; // Reads from Cookies, Form, QueryString, and ServerVariables - } - - void WebFormsHttpRequest(HttpRequest request) - { - _ = request.Form["id"]; // Compliant: HttpRequest is used in WebForms pages and is not the same as HttpRequestBase HttpRequest { get; } in a Controller - } - - // parameterized test: parameters are the different forbidden Request accesses (see above) - private static void HandleRequest(HttpRequestBase request) - { - _ = request.Form["id"]; // Noncompliant: Containing type is a controller - void LocalFunction() - { - _ = request.Form["id"]; // Noncompliant: Containing type is a controller - } - } -} - -public class CodeBlocksController : Controller -{ - public CodeBlocksController() - { - _ = Request.Form["id"]; // Noncompliant - } - - public CodeBlocksController(object o) => _ = Request.Form["id"]; // Noncompliant - - HttpRequestBase ValidRequest => Request; - NameValueCollection Form => Request.Form; - - string P1 => Request.Form["id"]; // Noncompliant - string P2 - { - get => Request.Form["id"]; // Noncompliant - set => Request.Form["id"] = value; // Noncompliant - } - string P3 - { - get - { - return Request.Form["id"]; // Noncompliant - } - set - { - Request.Form["id"] = value; // Noncompliant - } - } - void M1() => _ = Request.Form["id"]; // Noncompliant - void M2() - { - Func f1 = () => Request.Form["id"]; // Noncompliant - Func f2 = x => Request.Form["id"]; // Noncompliant - Func f3 = delegate (object x) { return Request.Form["id"]; }; // Noncompliant - } - void M3() - { - _ = (true ? Request.Form : Request.QueryString)["id"]; // FN: Noncompliant - _ = ValidatedRequest().Form["id"]; // Noncompliant - _ = ValidRequest.Form["id"]; - _ = Form["id"]; // FN: Noncompliant, requires cross method SE - _ = this.Form["id"]; // FN: Noncompliant, requires cross method SE - _ = new CodeBlocksController().Form["id"]; // Compliant - - HttpRequestBase ValidatedRequest() => Request; - } - - void M4() - { - _ = this.Request.Form["id"]; // Noncompliant - _ = Request?.Form?["id"]; // Noncompliant - _ = Request?.Form?.GetValues("id"); // Noncompliant - _ = Request.Form?.GetValues("id"); // Noncompliant - _ = Request.Form?.GetValues("id")?.ToString(); // Noncompliant - _ = HttpContext.Request.Form["id"]; // Noncompliant - _ = Request.RequestContext.HttpContext.Request.Form["id"]; // Noncompliant - _ = this.ControllerContext.RequestContext.HttpContext.Request.Form["id"]; // Noncompliant - var r1 = HttpContext.Request; _ = r1.Form["id"]; // Noncompliant - var r2 = ControllerContext; _ = r2.RequestContext.HttpContext.Request.Form["id"]; // Noncompliant - } - ~CodeBlocksController() => _ = Request.Form["id"]; // Noncompliant -} - -// parameterized test: Repeat for Controller, MyBaseController, MyBaseBaseController base classes -public class MyBaseController : Controller { } - -public class MyBaseBaseController : MyBaseController { } - -public class MyTestController : MyBaseBaseController -{ - public void Action() - { - _ = Request.Form["id"]; // Noncompliant - } -} - -public class OverridesController : Controller -{ - public void Action() - { - _ = Request.Form["id"]; // Noncompliant - } - private void Undecidable(HttpContextBase context) - { - // Implementation: It might be difficult to distinguish between access to "Request" that originate from overrides vs. "Request" access that originate from action methods. - // This is especially true for "Request" which originate from parameters like here. We may need to redeclare such cases as FNs (see e.g HandleRequest above). - _ = context.Request.Form["id"]; // Undecidable: request may originate from an action method (which supports binding), or from one of the following overrides (which don't). - } - private void Undecidable(HttpRequestBase request) - { - _ = request.Form["id"]; // Undecidable: request may originate from an action method (which supports binding), or from one of the following overloads (which don't). - } - - protected override void Initialize(RequestContext requestContext) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void Execute(RequestContext requestContext) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - return default; - } - protected override void OnActionExecuted(ActionExecutedContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnActionExecuting(ActionExecutingContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnAuthentication(AuthenticationContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnAuthorization(AuthorizationContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnException(ExceptionContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnResultExecuted(ResultExecutedContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void OnResultExecuting(ResultExecutingContext filterContext) - { - _ = filterContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } -} - -public class OverridesControllerBase : ControllerBase -{ - protected override void Initialize(RequestContext requestContext) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void Execute(RequestContext requestContext) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - protected override void ExecuteCore() => throw new NotImplementedException(); -} - -public class OverridesIController : IController -{ - public void Execute(RequestContext requestContext) - { - _ = requestContext.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } -} -static class HttpRequestExtensions -{ - // parameterized test: parameters are the different forbidden Request accesses (see above) - public static void Ext(this HttpRequestBase request) - { - _ = request.Form["id"]; // Compliant: Not in a controller - } -} - -class RequestService -{ - public HttpRequestBase Request { get; } - - // parameterized test: parameters are the different forbidden Request accesses (see above) - public void HandleRequest(HttpRequestBase request) - { - _ = Request.Form["id"]; // Compliant: Not in a controller - _ = request.Form["id"]; // Compliant: Not in a controller - } -} - -public class MyApiController : ApiController -{ - public void Action() - { - // this.Request.Form["key"] does not compile: Form is not defined. - // this.Request.QueryString["key"] does not compile: QueryString is not defined. - this.Request.GetQueryNameValuePairs(); // Compliant: Accesses the whole query at once for e.g. iteration and lookup. - _ = this.Request.GetQueryNameValuePairs().ToDictionary(kvp => kvp.Key, kvp => kvp.Value)["key"]; // FN: Too complicated to detect. - } -} \ No newline at end of file diff --git a/rules/S6932/S6932.AspNetCore.cs b/rules/S6932/S6932.AspNetCore.cs deleted file mode 100644 index 57dbbfd1a47..00000000000 --- a/rules/S6932/S6932.AspNetCore.cs +++ /dev/null @@ -1,256 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using System; -using System.Linq; -using System.Threading.Tasks; - -public class TestController : Controller -{ - private readonly string Key = "id"; - - public IActionResult Post() - { - _ = Request.Form["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^ - _ = Request.Form.TryGetValue("id", out _); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^ - _ = Request.Form.ContainsKey("id"); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^ - _ = Request.Headers["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^ - _ = Request.Headers.TryGetValue("id", out _); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^ - _ = Request.Headers.ContainsKey("id"); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^ - _ = Request.Query["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^ - _ = Request.Query.TryGetValue("id", out _); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^ - _ = Request.RouteValues["id"]; // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^^^^^ - _ = Request.RouteValues.TryGetValue("id", out _); // Noncompliant {{Use model binding instead of accessing the raw request data}} - // ^^^^^^^^^^^ - _ = Request.Form.Files; // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files["file"]; // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files[0]; // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files.Any(); // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files.Count; // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files.GetFile("file"); // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - _ = Request.Form.Files.GetFiles("file"); // Noncompliant {{Use IFormFile or IFormFileCollection binding instead}} - // ^^^^^ - return default; - } - - // Parameterized for "Form", "Query", "RouteValues", "Headers" - void NoncompliantKeyVariations() - { - _ = Request.Form[@"key"]; // Noncompliant - _ = Request.Form.TryGetValue(@"key", out _); // Noncompliant - _ = Request.Form["""key"""]; // Noncompliant - _ = Request.Form.TryGetValue("""key""", out _); // Noncompliant - - _ = Request.Form[Key]; // FN: Key is a readonly field with a constant initializer (Requires cross procedure SE) - const string key = "id"; - _ = Request.Form[key]; // Noncompliant - _ = Request.Form.TryGetValue(key, out _); // Noncompliant - _ = Request.Form[$"prefix.{key}"]; // Noncompliant - _ = Request.Form.TryGetValue($"prefix.{key}", out _); // Noncompliant - _ = Request.Form[$"""prefix.{key}"""]; // Noncompliant - _ = Request.Form.TryGetValue($"""prefix.{key}""", out _); // Noncompliant - string localKey = "id"; - _ = Request.Form[localKey]; // FN (Requires SE) - - _ = Request.Form[key: "id"]; // Noncompliant - _ = Request.Form.TryGetValue(value: out _, key: "id"); // Noncompliant - } - - // Parameterized for Form, Headers, Query, RouteValues / Request, this.Request, ControllerContext.HttpContext.Request / [FromForm], [FromQuery], [FromRoute], [FromHeader] - // Implementation: Consider adding a CombinatorialDataAttribute https://stackoverflow.com/a/75531690 - async Task Compliant([FromForm] string key) - { - _ = Request.Form.Keys; - _ = Request.Form.Count; - foreach (var kvp in Request.Form) { } - _ = Request.Form.Select(x => x); - _ = Request.Form[key]; // Compliant: The accessed key is not a compile time constant - _ = Request.Cookies["cookie"]; // Compliant: Cookies are not bound by default - _ = Request.QueryString; // Compliant: Accessing the whole raw string is fine. - _ = await Request.ReadFormAsync(); // Compliant: This might be used for optimization purposes e.g. conditional form value access. - } - - // parameterized test: parameters are the different forbidden Request accesses (see above) - private static void HandleRequest(HttpRequest request) - { - _ = request.Form["id"]; // Noncompliant: Containing type is a controller - void LocalFunction() - { - _ = request.Form["id"]; // Noncompliant: Containing type is a controller - } - static void StaticLocalFunction(HttpRequest request) - { - _ = request.Form["id"]; // Noncompliant: Containing type is a controller - } - } -} - -public class CodeBlocksController : Controller -{ - public CodeBlocksController() - { - _ = Request.Form["id"]; // Noncompliant - } - - public CodeBlocksController(object o) => _ = Request.Form["id"]; // Noncompliant - - HttpRequest ValidRequest => Request; - IFormCollection Form => Request.Form; - - string P1 => Request.Form["id"]; // Noncompliant - string P2 - { - get => Request.Form["id"]; // Noncompliant - } - string P3 - { - get - { - return Request.Form["id"]; // Noncompliant - } - } - void M1() => _ = Request.Form["id"]; // Noncompliant - void M2() - { - Func f1 = () => Request.Form["id"]; // Noncompliant - Func f2 = x => Request.Form["id"]; // Noncompliant - Func f3 = delegate (object x) { return Request.Form["id"]; }; // Noncompliant - } - void M3() - { - _ = (true ? Request : Request).Form["id"]; // Noncompliant - _ = ValidatedRequest().Form["id"]; // Noncompliant - _ = ValidRequest.Form["id"]; - _ = Form["id"]; // FN: Noncompliant, requires cross method SE - _ = this.Form["id"]; // FN: Noncompliant, requires cross method SE - _ = new CodeBlocksController().Form["id"]; // Compliant - - HttpRequest ValidatedRequest() => Request; - } - - void M4() - { - _ = this.Request.Form["id"]; // Noncompliant - _ = Request?.Form?["id"]; // Noncompliant - _ = Request?.Form?.TryGetValue("id", out _); // Noncompliant - _ = Request.Form?.TryGetValue("id", out _); // Noncompliant - _ = Request.Form?.TryGetValue("id", out _).ToString(); // Noncompliant - _ = HttpContext.Request.Form["id"]; // Noncompliant - _ = Request.HttpContext.Request.Form["id"]; // Noncompliant - _ = this.ControllerContext.HttpContext.Request.Form["id"]; // Noncompliant - var r1 = HttpContext.Request; _ = r1.Form["id"]; // Noncompliant - var r2 = ControllerContext; _ = r2.HttpContext.Request.Form["id"]; // Noncompliant - } - ~CodeBlocksController() => _ = Request.Form["id"]; // Noncompliant -} - - -// parameterized test: Repeat for Controller, ControllerBase, MyBaseController, MyBaseBaseController base classes -// consider adding "PageModel" to the parametrized test but functional tests and updates to the RSpec are needed. -public class MyBaseController : ControllerBase { } -public class MyBaseBaseController : MyBaseController { } -public class MyTestController : MyBaseBaseController -{ - public void Action() - { - _ = Request.Form["id"]; // Noncompliant - } -} - -public class OverridesController : Controller -{ - public void Action() - { - _ = Request.Form["id"]; // Noncompliant - } - private void Undecidable(HttpContext context) - { - // Implementation: It might be difficult to distinguish between access to "Request" that originate from overrides vs. "Request" access that originate from action methods. - // This is especially true for "Request" which originate from parameters like here. We may need to redeclare such cases as FNs (see e.g HandleRequest above). - _ = context.Request.Form["id"]; // Undecidable: request may originate from an action method (which supports binding), or from one of the following overrides (which don't). - } - private void Undecidable(HttpRequest request) - { - _ = request.Form["id"]; // Undecidable: request may originate from an action method (which supports binding), or from one of the following overloads (which don't). - } - public override void OnActionExecuted(ActionExecutedContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - public override void OnActionExecuting(ActionExecutingContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - return base.OnActionExecutionAsync(context, next); - } -} - -// parameterized test for PocoController, [Controller]Poco -// consider adding "PageModel" to the parametrized test but functional tests and updates to the RSpec are needed. -public class PocoController : IActionFilter, IAsyncActionFilter -{ - public void OnActionExecuted(ActionExecutedContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - void IActionFilter.OnActionExecuted(Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - public void OnActionExecuting(ActionExecutingContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - void IActionFilter.OnActionExecuting(ActionExecutingContext context) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - } - public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - return Task.CompletedTask; - } - Task IAsyncActionFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) - { - _ = context.HttpContext.Request.Form["id"]; // Compliant: Model binding is not supported here - return Task.CompletedTask; - } -} - -static class HttpRequestExtensions -{ - // parameterized test: parameters are the different forbidden Request accesses (see above) - public static void Ext(this HttpRequest request) - { - _ = request.Form["id"]; // Compliant: Not in a controller - } -} - -class RequestService -{ - public HttpRequest Request { get; } - // parameterized test: parameters are the different forbidden Request accesses (see above) - public void HandleRequest(HttpRequest request) - { - _ = Request.Form["id"]; // Compliant: Not in a controller - _ = request.Form["id"]; // Compliant: Not in a controller - } -} diff --git a/rules/S6962/csharp/metadata.json b/rules/S6962/csharp/metadata.json index 3d1773282d5..bf56d4f18d8 100644 --- a/rules/S6962/csharp/metadata.json +++ b/rules/S6962/csharp/metadata.json @@ -7,6 +7,7 @@ "constantCost": "1h" }, "tags": [ + "asp.net" ], "defaultSeverity": "Major", "ruleSpecification": "RSPEC-6962", diff --git a/rules/S6966/metadata.json b/rules/S6966/metadata.json index 58218429389..64890ea547e 100644 --- a/rules/S6966/metadata.json +++ b/rules/S6966/metadata.json @@ -7,6 +7,7 @@ "constantCost": "5min" }, "tags": [ + "asp.net", "async-await" ], "defaultSeverity": "Major", @@ -22,4 +23,4 @@ "attribute": "COMPLETE" } } - \ No newline at end of file +