It’s never the runtime… (Except when it is)

BugSomething I’ve learned over the course of many years working in IT is that when you hit a difficult to explain problem it’s very easy to say “it’s the runtime’s fault!” or “that’s a compiler bug” to cover for the lack of explanation for your problem. The vast majority of the time, it’s not true though. It’s just a subtler bug in your own work that you can’t see yet.

Every so often, however, it is true. And it turns out the issue I discussed the other week about Sitecore rendering a Razor error when you asked for a media item may well be an example of this.

Getting to the bottom of the issue…

When I wrote my previous post, my colleagues and I had worked out how to resolve the problem we saw, but didn’t understand what the underlying issue that caused it actually was. Since then one of my colleagues has spent further time discussing our situation with the team at Sitecore Support and they’ve provided some really helpful feedback about what the underlying issue might be. And the surprise is that they’re pinning it on a .Net Framework bug.

Their explanation describes a particular set of circumstances.

Each request you make goes through System.Web.WebPages.WebPageHttpModule which eventually calls System.Web.WebPages.WebPageRoute.MatchRequest(). Part of the logic inside that method calls WebPageRoute.FileExists(). That in turn depends on System.Web.Util.FileUtil.IsSuspiciousPhysicalPath() to look for some common scenarios that might indicate a malicious request. If all that succeeds, our media requests should end up with the custom handler that Sitecore provides for these URLs. But in the scenario we discovered the custom handler wasn’t called – but .Net’s Razor handler was instead.

In our particular situation, if the odd file “NOT_A_VALID_FILESYSTEM_PATH” existed in the website root, and the config setting for “relaxedUrlToFileSystemMapping” is set to True, then the IsSuspiciousPhysicalPath() method can mess things up when the path being processed is a certain length.

Support’s example was:

1) The next URL is requested: “http://a-test-server.local/~/media/Client-Name/print-resource-images/thumbnails/elected-representatives/Campaign-factsheet-Thumbnail-Nov-16-v3.ashx“.

2) CustomHandlers processor modifies the URL. Its current value is “http://a-test-server.local/~/media/Client-Name/print-resource-images/thumbnails/elected-representatives/sitecore_media.ashx/~/media/Client-Name/print-resource-images/thumbnails/elected-representatives/Campaign-factsheet-Thumbnail-Nov-16-v3.ashx“.

3) “IsSuspiciousPhysicalPath()” method is triggered. Physical path is “C:\Inetpub\wwwroot\a-test-server\Website\~\media\Client-Name\print-resource-images\thumbnails\elected-representatives\sitecore_media.ashx\~\media\Client-Name\print-resource-images\thumbnails\elected-representatives\Campaign-factsheet-Thumbnail-Nov-16-v3.ashx“. Please note that “/en“s are not included in physicalPath even if they are included in your request URL.

4) physicalPath.Length is 258. The value of “FileExists” is “false”.

5) “GetRouteLevelMatch(…)” modifies the URL. Its current value is “http://a-test-server.local/~/media/Client-Name/print-resource-images/thumbnails/elected-representatives/sitecore_media.ashx/~/media/Client-Name/print-resource-images/thumbnails/elected-representatives/Campaign-factsheet-Thumbnail-Nov-16-v3.ashx.cshtml“.

6) “IsSuspiciousPhysicalPath()” method is triggered. Physical path is “C:\Inetpub\wwwroot\a-test-server\Website\~\media\Client-Name\print-resource-images\thumbnails\elected-representatives\sitecore_media.ashx\~\media\Client-Name\print-resource-images\thumbnails\elected-representatives\Campaign-factsheet-Thumbnail-Nov-16-v3.ashx.cshtml“.

7) physicalPath.Length is 265. The value of “FileExists” is “true”. The path has a file extension, so the media item (“NOT_A_VALID_FILESYSTEM_PATH” file to be precise) is rendered as a razor view.

If the initial length of “physicalPath” string was 245, “/default.cshtml” would be added.

This is a bit complicated, but working through it with the public source for the relevant bits of .Net does seem to explain the odd behaviour we saw. Including the bit where changing the length of the URL could fix the problem, but certain invalid URLs would not return the expected 404.

Getting it fixed for the future…

Support have raised an issue with Microsoft to get the underlying bug investigated and resolved – so hopefully that will get sorted in a future update to the .Net runtime. They’ve also marked this as an issue in Sitecore using the bug number 95341 – so if you hit a similar issue that’s the number to report to Support.

And in the meantime, keep an eye out for “NOT_A_VALID_FILESYSTEM_PATH” getting accidentally created if Server.MapPath() processes URLs with invalid characters in it


One thought on “It’s never the runtime… (Except when it is)

  1. Pingback: What went wrong with my media? | Jeremy Davis

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s