12

I'm having problems with requests that include 'dangerous characters' as part of a Web API URL. The Url includes an & which is properly Url encoded, but still causes a Request Validation ASP.NET error.

Unlike MVC there appears to be no [ValidateInput(false)] attribute to force and disable this functionality.

4 Answers 4

8

Turns out the answer is to do this in web.config using:

<system.web>
  <httpRuntime requestPathInvalidCharacters="" />  
</system.web>

You can set this globally or at the sub-directory level. You can leverage the <location path=""> element to specify this setting only underneath certain paths. For example, if your Web API route that was affected lived underneath api/images you could do the following:

<location path="api/images">
  <system.web>
    <httpRuntime requestPathInvalidCharacters="" />  
  </system.web>
</location>

More information: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx

Sign up to request clarification or add additional context in comments.

2 Comments

This is the only solution that worked for me. Adding requestValidationMode='2.0' to the web.config and trying the [ValidateInput(false)] attribute on the action method did NOT work. It started working after I added requestPathInvalidCharacters="". I think this is because the error here is part of Request.Path validation rather than Request.Form validation.
It does not need to be global, just use location element to restrict path. So if your Web API route is under api/foo you can restrict location to path="api/foo" and add the httpRuntime configuration there. Confirmed this works fine in IIS. Also MSDN explictly states <httpRuntime> can be "declared at the machine, site, application, and subdirectory levels". I updated the answer.
3

With RequestValidation set to 4.0 in the configuration the answer is no. You can however revert back to 2.0 Request Validation in which case the MVC attribute works as you would expect: Validate by default and explicitly override when needed.

<httpRuntime executionTimeout="300" requestValidationMode="2.0" />

Talked in detail about this and some of the options here: http://www.west-wind.com/weblog/posts/2010/Aug/19/RequestValidation-Changes-in-ASPNET-40

Comments

3

You can get more fine-grained control over this by setting the requestValidationType attribute of the httpRuntime element to a custom type that inherits from System.Web.Util.RequestValidator and overrides IsValidRequestString.

Unfortunately this isn't part of the WebAPI pipeline, so can't directly check for things like action filters (i.e. attributes on controller methods).

However, if you specifically care about the Validation of Form fields, the Validator doesn't get called on these until you access them, which happens after Action Filters are fired, so you can opt-out of validation using an attribute by creating classes like the following...

public class AllowFormHtmlAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        HttpContext.Current.Items["AllowFormHtml"] = true;
    }
}

public class CustomRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (context.Items["AllowFormHtml"] as bool? == true && requestValidationSource == RequestValidationSource.Form)
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(
            context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}

... Then just annotating your controller method with [AllowFormHtml]

However, if you're accessing form fields directly from the HttpRequest, it's simpler to use HttpRequest.Unvalidated, which bypasses validation.

Comments

2

per @Levi our Web Security guy:

Config is the only way to do this. Even MVC’s [ValidateInput(false)] wouldn’t help with this particular scenario.

Disabling it in Web.config isn’t necessary a terrible idea. If you’re following good security practice by validating and encoding untrusted data, it’s perfectly fine to apply it application-wide.

1 Comment

[ValidateInput(false)] does not work in my case. I think it's because [ValidateInput(false)] refers to the Request.Form rather than Request.Path.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.