September 2020 included a several important security fixes for all supported versions of Sharepoint (2010, 2013, 2016 and 2019).
Some of these security fixes have tightend the security requirements for 1st party and 3rd party solutions integrated with SharePoint.
Affected Microsoft Products which integrate with SharePoint and which are affected by this change include Microsoft Identity Manager (MIM) portal pages and Dynamix AX.
Here is a quick summary of the requirements which are enforced now:
- code behind classes and web parts need to be explicitly registered as safe in the web.config using <SafeControl…> entries
- custom user controls (ascx pages) need to be explicitly registered as safe in the web.config using <SafeControl…> entries
- custom server controls need to be explicitly registered as safe in the web.config using <SafeControl…> entries
- inline code blocks in pages are blocked. Pages which require that have to be whitelisted explicitly using <PageParserPath…> entries in the web.config
- declarative statements in pages and master pages which invoke server side code (e.g. autoeventwireup, enablesessionstate, serverside event receivers for page actions, …) are blocked. Pages which require that have to whitelisted explicitly using <PageParserPath…> entries in the web.config
One or more of the following error message can occur for an affected page:
- The attribute ‘autoeventwireup’ is not allowed in this page.
- The attribute ‘enablesessionstate’ is not allowed in this page.
- Code blocks are not allowed in this file.
- The event handler ‘…’ is not allowed in this page. (… is a place holder and can mean any event type like OnClick, OnSelectedIndexChanged, …)
- UnsafeControlException: A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.
- The referenced file ‘/_layouts/somedirectory/affectedusercontrol.ascx’ is not allowed on this page.
Important: you should only whitelist affected pages and controls if these pages and controls are ghosted and remain ghosted. Ghosted means that they are deployed to the file system through custom solutions and are not modified afterwards using tools like SharePoint designer. Unghosted pages live in the SharePoint database while ghosted pages live on the file system. Modifications done through unghosting are not under the control of a SharePoint administrator and they should therefor be treated as unsafe and should not be unblocked.
Examples for web.config entries which can help to whitelist pages:
For blocked code behind files and server controls you need to whitelist the relevant classes using SafeControl elements similar to the following:
<SafeControl Assembly="CustomSolution.AssemblyName, Version=18.104.22.168,Culture=neutral, PublicKeyToken=11aa22bb33cc44dd" Namespace="CustomSolution.AssemblyName.NameSpace" TypeName="AffectedClass" AllowRemoteDesigner="True" Safe="True" SafeAgainstScript="True" />
Assembly, Namespace and TypeName in the above example has to be adjusted to reflect the information for the affected class.
If all controls and classes in a given assembly and namespace are safe you can use “*” as wildcard for the TypeName to whitelist all controls and classes at once. Please review your code carefully before applying this step to ensure that you are only whitelisting classes which are intended to be used in the affected pages.
To whitelist a directory hosting the affected user controls (.ascx) use a SafeControl element with the following syntax:
<SafeControls> <SafeControl Src="~/_layouts/somedirectory/*" IncludeSubFolders="True" Safe="True" AllowRemoteDesigner="True" SafeAgainstScript="True" /> </SafeControls>
<SafeControls> <SafeControl Src="~/_layouts/somedirectory/*" IncludeSubFolders="True" Safe="True" /> </SafeControls>
To whitelist pages or master pages which have inline code or include declarative statements which invoke server side code you need to whitelist them using a PageParserPath element similar to the following:
<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="15" TotalFileDependencies="250" AllowPageLevelTrace="false"> <PageParserPaths> <PageParserPath VirtualPath="/<relativepath>/page.aspx" CompilationMode="Always" AllowUnsafeControls="true" AllowServerSideScript="true" /> </PageParserPaths> </SafeMode>
Important: do not add IncludeSubFolders=”True” in this line when specifying a specific page as above!
VirtualPath is the server relative path starting at the root of your web application. In case you are using the same user control in multiple sites or collections you need to add a separate entry for each occurance.
To whitelist all controls in a given directory you can use the following syntax:
<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="15" TotalFileDependencies="250" AllowPageLevelTrace="false"> <PageParserPaths> <PageParserPath VirtualPath="/<relativepath>/*" CompilationMode="Always" AllowUnsafeControls="true" AllowServerSideScript="true" IncludeSubFolders="True"/> </PageParserPaths> </SafeMode>
Important: do NOT add VirtualPath=”/*” as this would effectively disable the security fix which was released in September 2020. Instead ensure to be a specific as possible for the VirtualPath to ensure that only pages are enabled which contain code that has been verified to be safe.
DirectFileDependencies indicates the number of allowed direct file dependencies. If you receive an error message such as “The number of allowed direct file dependencies exceeds the limit,” you can increase this value.
To simplify adding the PageParserPath elements to the web.config you can use the following powershell script created by Joe Rodgers which ensures that the entry is set on all servers in your farm:
See the following KB article for more information:
- KB 4584132 – Ghosted pages in SharePoint don’t render