Search code examples
c#appdomaincode-access-security

Code Access Security exception in restricted AppDomain


Goal: I need to run some code in an AppDomain with very limited permissions - it should have no access to anything at all fancy or unsafe, except for a few helper methods that I have defined elsewhere.

What I've done: I'm creating a sandbox AppDomain with the required basic permissions, and creating a proxy object, which runs the code:

static AppDomain CreateSandbox()
{
    var e = new Evidence();
    e.AddHostEvidence(new Zone(SecurityZone.Internet));

    var ps = SecurityManager.GetStandardSandbox(e);
    var security = new SecurityPermission(SecurityPermissionFlag.Execution);

    ps.AddPermission(security);

    var setup = new AppDomainSetup { 
        ApplicationBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 
    };
    return AppDomain.CreateDomain("Sandbox" + DateTime.Now, null, setup, ps);
}

public class Proxy : MarshalByRefObject
{
    public Proxy() { }

    public DoStuff()
    {
       // perform custom operation requiring permission
       HelperAssembly.HelperMethods.Method1();

       // do other stuff with low permission level
       ...
       ...
       ...   
    }
}

I've put the helper methods in a dedicated strong-named assembly, and marked them and their container class with [SecuritySafeCritical]:

// HelperAssembly.dll

namespace HelperAssembly
{
    [SecuritySafeCritical]
    public class HelperMethods
    {
        [SecuritySafeCritical]
        public static void Method1()
        {
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)
                .Assert();
            try
            {
                // logic requiring unmanaged code
                ...
            }
            finally
            {
                CodeAccessSecurity.RevertAll();
            }

        }
    }
}

Then, I load the helper assembly in the sandbox AppDomain and run Proxy.DoStuff(), expecting it to execute the helper method and be on its way:

var appDomain = CreateSandbox();

appDomain.Load(typeof(HelperAssembly.HelperMethods).Assembly.FullName);

var proxy = (Proxy)sandbox.CreateInstance(
    typeof(Proxy).Assembly.FullName, 
    typeof(Proxy).FullName).Unwrap();

proxy.DoStuff();

However, running the code causes an exception on the Assert() line in the helper method:

Unhandled Exception: System.InvalidOperationException: Cannot perform CAS Asserts in Security Transparent methods

What is the reason for this behavior and how can I achieve what I'm trying to do? To my understanding, the code in the untrusted AppDomain is security transparent, while the code in the helper assembly is security safe-critical, meaning it should be able to request permissions with Assert().

I'm obviously missing a piece of the puzzle, so it's up to someone with better understanding of Code Access Security to explain what is going wrong. Any help is appreciated.


Solution

  • Your "Trusted" assembly needs to have the AllowPartiallyTrustedCallers attribute for SecuritySafeCritical to be callable across assembly boundary. It must also be added to the fullTrustAssemblies in your call to CreateDomain.