Marking Your Code Transparent


Last week I discussed the concepts of security transparency and security critical code.  Now it’s time to get into the how-to’s


Marking an Entire Assembly Critical


This is by far the easiest of the operations … just do nothing [:D].  By default, all assemblies compiled for the v1.x and v2.0 frameworks are security critical and contain only critical code.  However, this default may change in the future.  It’s possible that when we release the next framework we’ll decide to make assemblies compiled for that version transparent by default.


Marking an Entire Assembly Transparent


The next easiest operation is marking an entire assembly as containing only security transparent code. To do this, simply mark the assembly with the System.Security.SecurityTransparentAttributeAttribute:



[assembly: SecurityTransparent]

This has the effect of saying that the assembly may not contain any critical code, and therefore will not elevate the privileges of the call stack due to the restrictions mentioned in the last article. 


Mixing Critical and Transparent Code in the Same Assembly


A more common scenario arises when you want to mix critical and transparent code in the same assembly.  In that case you start by marking the assembly with the System.Security.SecurityCriticalAttribute:



[assembly: SecurityCritical]

What this says is somewhat counter-intuitive.  By marking the assembly with the SecurityCriticalAttribute, you’re saying that the assembly can contain critical code, however unless explicitly marked all code within the assembly will default to being transparent.  In other words, if you want to perform security critical actions, you’ll need explicitly mark the code that will perform the critical action with another SecurityCritical attribute.


When you’re marking the critical section of code with its SecurityCritical attribute, you have two options.  The first choice is to mark a block of code (such as a method or property getter or setter) with a SecurityCriticalAttribute which says that the marked method contains critical code.  Your other option is to mark something that contains several blocks of code (such as an assembly with several methods) with the SecurityCriticalAttribute passing it a parameter of SecurityCriticalScope.Everything.  That has the effect of saying all blocks of code under this scope are critical.



Examples


Some examples may help clear things up:


 Lets start with:



public class A
{
    public void Foo()
    {
        // critical
    }

    public int Bar
    {
        get { /* critical */ }
        set { /* critical */ }
    }
}

public class B
{
    internal string Baz
    {
        get { /* critical */ }
        set { /* critical */ }
    }
}

This assembly contains only critical code, since there are no SecurityTransparent or SecurityCritical attributes on the assembly level.  This is the default configuration, meaning if you don’t explicitly start to use transparency, there will be no restrictions on what your code can do.  If we wanted everything to be transparent:



[assembly: SecurityTransparent]

public class A
{
    public void Foo()
    {
         // transparent
    } 

    public int Bar
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

public class B
{
    internal string Baz
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

This assembly is marked with the SecurityTransparentAttribute.  No further work is needed — because the assembly is marked transparent, all of its code is also transparent.  Note that this assembly:



[assembly: SecurityCritical]

public class A
{
    public void Foo()
    {
        // transparent
    }

    public int Bar
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

public class B
{
    internal string Baz
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

Also is entirely transparent, even though it was marked with the SecurityCritical attribute.  The reason is that SecurityCritical means the assembly may contain critical code.  But since none of the code in the assembly is marked critical, it all defaults to being transparent.  In this assembly however:



[assembly: SecurityCritical]

public class A
{
    [SecurityCritical]
    public void Foo()
    {
        // critical
    }

    public int Bar
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

public class B
{
    internal string Baz
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

Method A::Bar is marked with a separate SecurityCritical attribute.  Combined with the assembly level SecurityCriticalAttribute, this means that all the code in the assembly is transparent with the exception of A::Bar, which is critical.  Similarly:



[assembly: SecurityCritical]

public class A
{
    public void Foo()
    {
        // transparent
    }

    public int Bar
    {
        [SecurityCritical]
        get { /* critical */ }
        set { /* transparent */ }
    }
}

public class B
{
    internal string Baz
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

This assembly is entirely transparent with the exception of the property getter for A::Bar.  Notice that the SecurityCriticalAttribute goes on the getter and setter of the property, not on the property declaration itself.  In this case, only the getter is critical since the setter was not marked with its own SecurityCriticalAttribute.  Finally:



[assembly: SecurityCritical]

[SecurityCritical(SecurityCriticalScope.Everything)]
public class A
{
    public void Foo()
    {
        // critical
    }

    public int Bar
    {
        get { /* critical */ }
        set { /* critical */  }
    }
}

public class B
{
    internal string Baz
    {
        get { /* transparent */ }
        set { /* transparent */ }
    }
}

In this assembly all of the code that appears as a part of class A is critical, since A was marked with the SecurityCriticalAttribute with a scope of Everything.

Comments (8)

  1. I think the paragraph above that begins "Method A::Bar is marked with a separate SecurityCritical attribute…" is incorrect. Instead, in the example, only the assembly and A::Foo() are decorated with the SecurityCritical attribute, which as I understand your explanation indicates A:Foo, not A::Bar, is the only critical method in the assembly example.

    However, thanks for your articles on this topic they’re very helpful to understanding the notion of transparent and critical code.

  2. Syed Atif Shabbir says:

    Yeah I agree with Scott. It should be A::Foo() as the SecurityCritical attriubte.

  3. Dennes says:

     

    O .NET 2.0 traz novos conceitos de segurança, tal como os Assemblys transparentes e opacos. Esse…

  4. FxCop says:

    Last week we had a push to fix many of the issues reported on the forum and include them in the FxCop…

  5. FxCop says:

    Last week we had a push to fix many of the issues reported on the forum and include them in the FxCop…

  6. Last week we had a push to fix many of the issues reported on the forum and include them in the FxCop

  7. The story so far … And now for more of the adventures of Jack Bauer! ;). So since I posted the first

  8. Yesterday we talked about the CoreCLR security model , and how it is built upon the transparency model