Change the Default Trust Level
Recall that the root web.config
file has a setting that looks like this in a pristine installation of .NET:
<trust level="Full" originUrl="" />
There is nothing stopping you from changing this setting in the root web.config
file and, in fact, that is what many web hosting companies do to provide a layer of security between the many web applications that might be running on a single server. By the way, the originUrl
attribute is used to specify the URL of origin for the application for the WebPermission class, such as to allow connectivity back to the host of origin. You don't need to set this for the sample application.
You can override the trust level setting in any application by adding the trust
element to your application's web.config
file. To change the trust level for this article's sample application, add this line to its web.config
(in the sample application you can instead uncomment the line if you wish):
<trust level="Medium" />
When you change from running with Full trust, the CLR and ASP.NET have to do a little more work when the assembly loads. They run through a basic five-step operation:
- The CLR parses the appropriate <trust> level setting and retrieves the value.
- The CLR loads the appropriate policy file, in this case web_mediumtrust.config.
- Placeholder variables, such as $AppDir$, are replaced with the actual runtime values.
- The CLR calls the AppDomain.SetAppDomainPolicy method to set the trust level for the application domain and the code executes. (Remember that this is the fourth policy level for .NET applications.)
- While the assembly is loaded, the CLR monitors the appropriate policy file for any changes. If any changes occur, the CLR tears down the app domain and rebuilds it with the new settings.
Make the change in the trust level and re-run the application. Click on the Get Contents or Get Path buttons and, given the absence of exception handling in the code, you'll be greeted by the unhandled exception shown in Figure 5
. The crucial part of the message is "Request for the permission of type 'FileIOPermission' failed."
Attempting to read the PATH
environment variable returns no better results as you can see in Figure 6
. Here the permission that is unavailable is EnvironmentPermission
. In a real application, of course, you'd catch these exceptions either at the method level or in a global exception handler.
|Figure 5: When the sample application runs with Medium trust, you can no longer read eula.txt in the System32 directory.||
|Figure 6: In Medium trust, you also cannot read the PATH environment variable.||
So what's going on? Aren't the FileIOPermission
part of the Medium trust level? They are. So what gives? The problem is that each of those permissions is granted in a restricted form, and the restrictions don't include reading eula.txt
(or any file in System32) nor reading the PATH
environment variable. This means that the Medium trust level won't work for this application.
What are the options to make the application run? You can choose from several:
- If the protected operations—here to read eula.txt and the PATH variable—are not critical application requirements, get rid of the features. If they aren't critical, it is better to get rid of them rather than fiddle with security and maybe open nasty vulnerabilities!
- Use another standard trust level. Besides Full trust, the only other more permissive option than Medium is High trust. But this is likely to have way more permissions than your application requires, which opens up potential security vulnerabilities. That pretty much eliminates this as a viable option.
- Create a custom trust level with exactly the permissions your application needs. This is often the best choice since none of the standard trust levels are likely to exactly fit your needs.
- Sandbox dangerous code into a separate, well-protected assembly. This is often a good choice when the entire application doesn't need elevated privileges, just a small section of the code. This way the potential security vulnerabilities are strictly limited.
The option you select depends on the nature of your application and its requirements. For the example in this article, I'm going to alter the scenario of the sample application a bit. Let's say that the ability to read eula.txt
is something that has to happen throughout the application—Microsoft would be so proud!—and that slightly different code is needed each time. This means that you couldn't easily partition the file access code into a separate assembly. So the entire application needs the ability to read the eula.txt
file—and only read it. For this I'll create a custom trust level to add the necessary permission.
Let's say that reading and updating the PATH
variable is needed in just one place in the entire application, or that you want to use the same code over and over to do the same thing. This is a perfect use for sandboxing the Environment code—putting it in a separate assembly that receives the elevated privileges while leaving the main application's permissions alone.
Create a Custom Trust Level
You have to follow three basic steps to create a custom trust level and apply it to the sample application:
- Create the custom policy level file.
- Put the required permissions in the custom policy file.
- Set the application to use the custom trust level.
In the first step you create the policy level file. It is usually easiest to start with one of the standard policy files, and since the Medium trust level is close to what you need, you can copy that file to your application directory and rename it. So copy web_mediumtrust.config
from the .NET Framework CONFIG directory to the application directory and name it web_customtrust.config
Next you need to change the policy file to provide the FileIOPermission needed. You don't need to change the SecurityClasses section because FileIOPermission is already listed. And you don't need to change the CodeGroup
section because the application will still meet the membership condition for the code group associated with the ASP.Net
permission set. So you only need to change the permission set. Using the FileIOPermission (which is already part of the set) you can modify that element by adding the eula.txt
file to the Read
attribute of the permission, delimiting it from other entries with a semicolon:
If FileIOPermission were not already in the policy file, we'd have to add it. How do you know what XML to use? The SecurityClass
elements in the policy file are derived from the serialized form of the permission object. So you can write code like this to generate the elements and attributes you need in a console application:
EnvironmentPermission envPerm =
This code generates the following output, from which you can extract the information you need:
<IPermission class=" EnvironmentPermission,
mscorlib, Version=18.104.22.168, Culture=neutral,
In the final step you'll change the application web.config
file to use the custom trust level. This requires both a securityPolicy
element to define the trust level and associate the policy file with the custom level, and a trust
element to actually set the trust level:
<trust level="CustomTrust" originUrl=""/>
That's all that is necessary. Run the application again and see that it can read the eula.txt
file without problem. Try entering ..\..\boot.ini
however, and it raises an exception saying that the FileIOPermission needed is not available. That's because the CLR will only allow the operations defined in the IPermission
element above, none of which involve boot.ini. Now, the application can only read eula.txt
; any other file will throw the exception. The sample application is already more secure by using a modification of the Medium trust level rather than Full trust.