ASP.NET Trust Level Implementation
To understand how ASP.NET implements trust levels, you have to explore sections of the root .NET configuration files. You'll normally find these in the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG
directory, although your actual name may vary a bit depending on the name of your Windows directory and the Framework version. Since this application deals only with ASP.NET features here, I won't bother reviewing the sections of machine.config
, which contains settings for all .NET applications on the machine. Instead I'll just review the root web.config
file, the basis for all ASP.NET applications.
Near the top of the root web.config
file you'll find the <securityPolicy>
<trust level="Full" originUrl="" />
section defines the standard trust levels in ASP.NET: Full
, and Minimal
. Each level grants your assemblies a set of specific permissions, going from unlimited permissions in Full trust to absurdly restrictive permissions in the Minimal trust level. The policyFile
attribute specifies the file where the trust level is defined. The Full trust level uses "internal"
as the policy file name; this level needs no additional configuration file because permission checking is effectively shut off.
element sets the default trust level for all ASP.NET applications that don't override this setting. As you can see in the code above, it is set to Full
when you install the .NET Framework, which becomes the default for all web applications on the machine. Fortunately you can—and should—override it in each application's web.config
In my opinion, a good starting level for most ASP.NET applications is the Medium trust level because it grants a reasonable set of permissions needed for most common web applications. The High trust level has far too many permissions, but at least it is better than Full because High doesn't allow running unmanaged code. Low and Minimal have far too few permissions to realistically run any non-trivial web application. So I'll use the Medium trust level as the starting point.
By the way, Microsoft's names for these trust levels might be a bit confusing. The higher the trust level, the more you trust the code is secure, and the more permissions it has. Low and Minimal ASP.NET applications are very untrustworthy, so they have too few permissions to realistically run a web application. High means that it is highly trusted code and it has almost all available .NET permissions. All this mumbo jumbo is yet another good reason to use a custom trust level tailored for the needs of a specific application.
If you examine the Medium trust level policy file, web_mediumtrust.config
, you can see how ASP.NET defines a trust level. There are three major sections in this XML file: <SecurityClasses>
, and <CodeGroup>
. SecurityClasses includes a SecurityClass
element for every permission, membership condition, and code group object used in this policy file. Each class is given an internal "friendly" name with the Name
attribute and the Description
attribute includes the strong name of the class. For example, this next code snippet shows the SecurityClass
element for the permission that allows the code to connect to a SQL Server database (I've added line breaks to fit in the space; the entry is all on one line in the policy file):
System.Data, Version=188.8.131.52, Culture=neutral,
The policy file includes three named permission sets: FullTrust
, and ASP.Net
. The FullTrust
permission set is again a special case. It doesn't have to list any permissions because the code has all permissions. Below you can see the FullTrust
permission set definition:
Description="Allows full access to all resources"
attribute is the important setting here. It tells the CLR to turn off permission checking for this assembly. The value of the Name
, is how the file assigns this set of permissions to a code group, which I'll get to soon.
permission set, shown below, is of no real interest here. If an assembly has this trust level, it can do absolutely nothing, not even execute, so you're not likely to use it in most applications.
Description="Denies all resources, including
the right to execute"
permission set is what is interesting for partial trust applications. Through the <trust>
element, it is the permission set assigned to the assembly, in this case at the Medium trust level. Here the policy file defines the specific permissions that will be assigned to an assembly at this trust level. This section begins with a PermissionSet
element to define the name of the set:
The children of PermissionSet
define the permissions that make up the set, contained within IPermission
elements. Here is the IPermission
element for the SqlClientPermission:
This is the unrestricted
form of a permission (Unrestricted="true"), meaning that code with a Medium trust level will have full access to SQL Server databases, without any limitations or restriction. That makes sense for database access, because once you allow code to connect to a database, it is up to the database to enforce any security restrictions.
Now let me illustrate a couple of restricted
You can tell that these are restricted forms of the permissions because they don't have the Unrestricted
attribute set to true and they have one or more additional attributes that define the restriction. The EnvironmentPermission
here allows read-only access to the TEMP
, and COMPUTERNAME
environment variables only. It can't write to those variables, nor can it read or write any others that may exist on this machine. Note in particular that the Medium trust level grants no access to the PATH
variable used by the sample application. I'll discuss that in more detail a little later in this article.
The FileIOPermission in Medium trust is also a restricted form of the permission, with four attributes defining the restriction. In this case the permission uses variables—with names starting and ending with a dollar sign—as placeholders for runtime values. $AppDir$
is the applications root directory. You can also use $AppDirUrl$
for the URI format of the root directory name (using the file://
for the temporary ASP.NET assembly directory, and $OriginHost$
for URIs that the application can connect to.
After the NamePermissionSet
section in the medium trust policy file, you'll find the <CodeGroup>
section. The policy file uses these elements to match assemblies with permission sets by assigning the assembly to one or more code groups. There is rich support for structuring a hierarchy of code groups, which gives you fine control over exactly which permissions sets an assembly gets. I'll gloss over most of the details here and let you explore them in the documentation. (See the sidebar, Help Writing Secure ASP.NET Applications
, for a reference that goes into good detail about this hierarchy.)
Here is the CodeGroup
element that assigns your web application's assemblies to the ASP.Net
element is of type UnionCodeGroup, which means that its permissions are added to those in the hierarchy. The PermissionSetName
attribute links it to the ASP.Net
permission set defined earlier in the file, and the IMembershipCondition
element defines which assemblies belong to this code group. Here the membership condition is based on the location of the assembly, specifically all those in the application directory. This is how the assemblies you create as part of an ASP.NET application get the ASP.Net
permission set that is part of the trust level defined by this config file.
Now that you understand how ASP.NET implements trust levels, let's look at how to change the trust level for an application.