Engineered Code is proud to announce the availability of ecLearn - the Learning Management System built on top of Microsoft Dataverse

ENGINEERED CODE BLOG

Incorrect Content Type for JavaScript File in Dynamics 365 Portals

When one of our clients who is using xRM Portals Community Edition wanted to batten down the hatches from a security perspective, we discovered that a core JavaScript file of Dynamics 365 Portals is being served with the incorrect content type.

Securing Your Portal with Response Headers

When you run an online security vulnerability assessment tool, such as the one available at Pentest-Tools.com, one of the recommendations you’ll often run into is to set a few security-related response headers, including X-Frame-Options, X-Xss-Protection, and X-Content-Type-Options.

X-Frame-Options allows you to control whether your site can be loaded within an IFrame; possible values include DENY, SAMEORIGIN, and ALLOW-FROM. DENY means that a browser should not display the site in an IFrame, whereas SAMEORIGIN will allow a site to be loaded in an IFrame as long as it’s on the same domain (depending on the browser implementation, subdomains may or may not work). The ALLOW-FROM option allows an administrator to provide a list of domains that are allowed to display the site in an IFrame. The DENY option is generally recommended.

X-Xss-Protection provides options to determine how a browser should act when they detect a cross-site scripting attack. Setting this header to 0 turns off the filtering, a value of 1 means that the part of the page containing the attack is sanitized (removed), and a value of 1; mode=block will stop the entire page from rendering. This last value is recommended.

X-Content-Type-Options has a single option: nosniff. This means that the browser does not attempt to determine the type of a file based on its contents; it will only use the Content-Type header.

We were able to add these headers to our responses by adding the following section to our web.config file:

<system.webServer>
	<httpProtocol>
		<customHeaders>
			<add name="X-Frame-Options" value="SAMEORIGIN" />
			<add name="X-Xss-Protection" value="1; mode=block" />
			<add name="X-Content-Type-Options" value="nosniff" />
		</customHeaders>
	<httpProtocol>
</system.webServer>

It was this last header, X-Content-Type-Options, that caused our issues.

Portal Resource Manager

The file that caused us grief is the Resource Manager, which can be found at (depending on your language):

https://portalurl/_resources/getresourcemanager?lang=en-US

This is a relatively simple, but long, JavaScript file that contains the text for a lot of the messages you see throughout the portal. The file contains almost five hundred messages, and the query string parameter determines the language. It adds an object called ResourceManager to the window context. This object (window.ResourceManager) is referenced throughout the code and, as you can imagine, you’re going to have problems if this file fails to load.

The issue here is, if you look at the response when you request this file, the Content-Type header is text/html; charset=utf-8, instead of the text/javascript that you’d typically expect for a JavaScript file. Once you add the X-Content-Type-Options: nosniff header, your browser will no longer load the ResourceManager script because the file is being sent as text/html.

Digging Into the Source Code

Thankfully, because we have the full source code with the xRM Portals Community Edition, we are able to see what’s going on. The files of interest are:

  • Areas\Portal\Views\Resources\ResourceManager.ascx
  • Areas\Portal\Controllers\ResourcesController.cs

If you look in the ResourceController.cs file, you’ll see that the Content-Type header is being set:

Response.ContentType = "text/javascript";

However, that line of code does not do anything. It seems to be an MVC issue; whatever you set as the ContentType in the controller is not respected if you return a View.

The recommended solution I found with the help of Google was to include the following line on the view itself:

<% this.Response.ContentType = "text/javascript"; %>

However, this still didn’t do the trick. For some reason, this didn’t work if the view being returned was a user control (.ascx). So, I renamed the file from ResourceManager.ascx to ResourceManager.aspx, and replaced the first two lines in the file with the following:

<%@ Page Language="C#" %>
<%@ Import Namespace="Adxstudio.Xrm.Resources" %>
<% this.Response.ContentType = "text/javascript"; %>

Once I did that, the file finally was returning the text/javascript content type.

What Does This Mean for Dynamics 365 Portals?

While the Microsoft-hosted Dynamics 365 Portals do exhibit this same issue, it doesn’t cause any errors because we aren’t able to add the X-Content-Type-Options: nosniff header to our responses since we don’t have access to the code. That being said, hopefully this is something that Microsoft will resolve in a future release, as it was clearly their intention to set the proper content type header.

3 responses to “Incorrect Content Type for JavaScript File in Dynamics 365 Portals”

  1. […] post Incorrect Content Type for JavaScript File in Dynamics 365 Portals appeared first on Engineered […]

  2. […] post Incorrect Content Type for JavaScript File in Dynamics 365 Portals appeared first on Engineered […]

  3. JV says:

    Thank you, extremely helpful.

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact

Engineered Code is a web application development firm and Microsoft Partner specializing in web portals backed by Dynamics 365 & Power Platform. Led by a professional engineer, our team of technology experts are based in Regina, Saskatchewan, Canada.