'How to prevent NetCore Web API to expose internals when Json is malformed?

When a malformed Json is sent to a NetCore Web Api method the default serializer Text.Json exposes the internal information in the error response.

DTO:

public record CreateGroupDTO(
            Guid AccountId,
            DateTime Start 
           );

Method in GroupsController (since the error is handled in the framework the code of the controller is off the point):

[HttpPost]
[Route("")]
public ActionResult<GroupDTO> CreateGroup(CreateGroupDTO createGroupDTO) {...}

Post with malformed Guid:

{
  "accountId": "4-5717-4562-b3fc-2c963f66afa6",
  "start": "2022-02-14T12:39:59.244Z"
}

Response Body:

    "errors": {
        "createGroupDTO": [
          "The createGroupDTO field is required."
        ],
        "$.accountId": [
          "The JSON value could not be converted to Elwis.Orders.Application.CreateGroupDTO.
          Path: $.accountId | LineNumber: 1 | BytePositionInLine: 52."
        ]
      }

Post with malformed DateTime:

{
  "accountId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "start": "2022-02-30"
}

Response Body:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-8f49393621db7dea28f797f4ee69f203-2612b8bd5fe0aa0d-00",
  "errors": {
    "createGroupDTO": [
      "The createGroupDTO field is required."
    ],
    "$.start": [
      "The JSON value could not be converted to Elwis.Orders.Application.CreateGroupDTO. Path: $.start | LineNumber: 2 | BytePositionInLine: 23."
    ]
  }
}

For security reasons the response should not expose the FullName of the dto type. How can I make Web API prevent exposing the FullName?

I also don't understand why the error for accountId is stating the dto. It should state that the JSON value could not be converted to Guid. How can I make Web API state a more correct error message?

UPDATE:

.Net 6 has a new option AllowInputFormatterExceptionMessages, that solves the main part of the problem (ASP.NET 6.0 Docs). You can add to StartUp.cs

services.AddControllers()
   .AddJsonOptions(o => o.AllowInputFormatterExceptionMessages = false);

Response for malformed Guid:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-a5036b75970685554b4cf7c87c452939-ca3293d1faef0d84-00",
  "errors": {
    "createGroupDTO": [
      "The createGroupDTO field is required."
    ],
    "$.accountId": [
      "The input was not valid."
    ]
  }
}

It still exposes the variable name of the body parameter It still states that "The createGroupDTO field is required."! This response makes no sense since it is not a field in the Json structure and just an internal name. Is there a way to prevent this?

Update 2:

I filed an issue at GitHub. Microsoft moved "this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s)."



Solution 1:[1]

In general it does not return the fullname, you need to provide the model. Or there is simple way, You can try to custom error message, I write a simple demo here.

custom error message

public class ReformatValidationProblemAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            if (context.Result is BadRequestObjectResult badRequestObjectResult)
                if (badRequestObjectResult.Value is ValidationProblemDetails)
                {
                    context.Result = new BadRequestObjectResult("Json is malformed");
                }

            base.OnResultExecuting(context);
        }
    }

controller

[ReformatValidationProblem]
    [Route("api/[controller]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
       //........
    }

register it in startup.cs

services.AddMvc(options =>
{
    options.Filters.Add(typeof(ReformatValidationProblemAttribute));
});

Then you can see when Json is malformed, It just return the custom error message instead of the fullName.

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1