Creating an AppDomain with limited permissions

Oftentimes in an application, it’s necessary to run untrusted code.  The CLR lets you do this safely by placing the code in its own AppDomain and sandboxing the AppDomain to have a limited set of permissions.  Usually setting up the AppDomain with the Internet permission set allows you to feel confident in executing arbitrary managed code.  Doing this is relatively easy, here’s a code snippet that takes advantage of last week’s GetNamedPermissionSet method in order to create a sandboxed AppDomain:

/// <summary>
/// Create an AppDomain that contains policy restricting code to execute
/// with only the permissions granted by a named permission set
/// </summary>
/// <param name=”permissionSetName”>name of the permission set to restrict to</param>
/// <exception cref=”ArgumentNullException”>
/// if <paramref name=”permissionSetName”/> is null
/// </exception>
/// <exception cref=”ArgumentOutOfRangeException”>
/// if <paramref name=”permissionSetName”/> is empty
/// </exception>
/// <returns>AppDomain with a restricted security policy</returns>
public static AppDomain CreateRestrictedDomain(string permissionSetName)
    if(permissionSetName == null)
        throw new ArgumentNullException(“permissionSetName”);
    if(permissionSetName.Length == 0)
        throw new ArgumentOutOfRangeException(“permissionSetName”, permissionSetName, “Cannot have an empty permission set name”);
    // Default to all code getting nothing
    PolicyStatement emptyPolicy = new PolicyStatement(new PermissionSet(PermissionState.None));
    UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), emptyPolicy);

    // Grant all code the named permission set passed in
    PolicyStatement permissions = new PolicyStatement(GetNamedPermissionSet(permissionSetName));
    policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), permissions));
    // create an AppDomain policy level for the policy tree
    PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel();
    appDomainLevel.RootCodeGroup = policyRoot;

    // create an AppDomain where this policy will be in effect
    string domainName = String.Format(“Restricted Domain: {0}”, permissionSetName)
    AppDomain restrictedDomain = AppDomain.CreateDomain(domainName);

    return restrictedDomain;

The code is pretty straight forward.  First I create a code group that grants AllCode no permission (similar to how the other policy levels create their root code group.)  The reason for this is that I’d like the flexibility of having multiple code groups on this AppDomain if necessary, and I can only have one root code group.  By setting the root code group to AllCode -> Nothing, I can then chain as many child code groups as I want onto that root.

In this case, the only child code group I create assigns AllCode the permission set named in the parameter of the method call.  Once this policy is set up, I create an AppDomain PolicyLevel, and assign the code groups to that level.

At that point, the only thing left to do is create the AppDomain and set its policy level.  This is easily done with the CreateDomain and SetAppDomainPolicy methods of the AppDomain class.

One important point to note is that setting the AppDomain policy must be done before any code is loaded into the AppDomain, and may only be done once.  As soon as code gets loaded into the AppDomain any changes to the security policy of that domain will no longer have any effect.

Another point is that this sandbox could be made even more secure by assigning some evidence to the AppDomain itself.  For instance, if I was planning on creating an AppDomain with the Internet named permission set, I might assign the AppDomain some evidence including Internet zone and a URL.

Comments (10)

  1. Kevin Westhead says:

    Could you elaborate on why you would assign evidence to the AppDomain? In other words, how does it make the AppDomain more secure and what potential security holes does it plug that permission sets alone cannot?

  2. Shawn says:

    Hi Kevin,

    Good question … I think I may turn this into a seperate post. The easiest example of an instance where an AppDomain needs evidence assigned to it is the case where a web page is hosting some managed code. In this case, the page might point at some code that lives on the local machine in the GAC, and therefore recieves a high level of trust.

    Now imagine that an exploit is found in this code, and by calling into a specific entry point, I can elevate my permissions and do whatever I want. Now, if my web page doesn’t load any code of its own, the only code on the callstack will be the buggy component in the application. This means that if you don’t take into account the AppDomain, an arbitrary web page can now exploit code sitting on my machine.

    Thankfully we do take the AppDomain into account, and all code hosted on a web page gets run in an AppDomain with a set of evidence that severly limits its permission grant. For more information about that (from the other perspective) check out:


  3. A while back I gave some sample code to show how to setup a sandboxed AppDomain.&amp;nbsp; This technique…