Export (0) Print
Expand All

Security transparent code should not reference non-public security critical members

TypeName

SecurityTransparentCodeShouldNotReferenceNonpublicSecurityCriticalCode

CheckId

CA2129

Category

Microsoft.Security

Breaking Change

Breaking

Methods that are marked with SecurityTransparentAttribute call non-public members that are marked as SecurityCritical. SecurityTransparent is the default designation for methods.

The .NET Framework 2.0 introduced a feature named transparency. Individual methods, fields, interfaces, classes, and types can be either transparent or critical.

Transparent code is not allowed to elevate security privileges. Therefore, any permissions granted or demanded of it are automatically passed through the code to the caller or host AppDomain. Examples of elevations include Asserts, LinkDemands, SuppressUnmanagedCode, and unsafe code.

The purpose of separating transparent and critical code is to simplify the security auditing process. Audits are typically performed on public entry points because of the chance of malicious and untrusted public usage. By marking smaller sections of an assembly as critical, the security audit can be reduced to public entry points and the security critical sections of code that elevate privileges. However, to make sure that the audit is accurate and complete, the boundary between transparent and critical code must be enforced as strongly as possible. The alternative would be to allow transparent code to call internal security critical code, which requires the transparent code to be more heavily audited.

At run time, the common language runtime just-in-time compiler checks if transparent code is referencing or calling non-public security critical code. If a call is made from transparent code to non-public critical code, an exception such as a MethodAccessException would be thrown. This is handled similarly to a class trying to access the private members of another class.

This code analysis rule analyzes all methods and types in an assembly which is mixed transparent/critical. This rule also flags any calls from transparent code to non-public critical code that are not marked SecurityTreatAsSafe.

To resolve the issue, either mark the code which calls the non-public SecurityCritical code as SecurityCritical, or mark the target method/type as SecurityTreatAsSafe. This effectively treats the code as public safe and audited to protect against malicious purposes.

Do not suppress a message from this rule.

The following code will fail because SecondSecurityMethod is private and SecurityCritical. As an example of a security issue, the Assert in SecondSecurityMethod will prevent full demands in privileged actions and call-outs to flow to FirstSecurityMethod, limited to the security checks that are performed on the caller.

using System;
using System.Security.Permissions;

namespace SecurityTestClassLibrary
{
    public class SecurityTestClass
    {
        // SecurityTransparent 
        public void FirstSecurityMethod()
        {
            SecondSecurityMethod();
        }

        [System.Security.SecurityCritical]
        private void SecondSecurityMethod()
        {
            // Assert permissions 

            // do privileged actions, such as method call-outs
        }
    }
}

If the transparent/critical boundary was not enforced, FirstSecurityMethod would then be able to perform all SecondSecurityMethod's actions without security checks.

One option is to code review the method, and if the method is considered safe for elevation, and safe from malicious attacks, mark it with SecurityTreatAsSafe:

using System;
using System.Security.Permissions;

namespace SecurityTestClassLibrary
{
    public class SecurityTestClass
    {
        // SecurityTransparent 
        public void FirstSecurityMethod()
        {
            SecondSecurityMethod();
        }

        [System.Security.SecurityTreatAsSafe]
        [System.Security.SecurityCritical]
        private void SecondSecurityMethod()
        {
            // Assert permissions 

            // do privileged actions, such as method call-outs
        }
    }
}

Another option is to make Method1 also Critical. This expands the critical kernel of the assembly and increases the size of the security audit. It also guarantees that appropriate threat modeling and code flow analysis is performed.

using System;
using System.Security.Permissions;

namespace SecurityTestClassLibrary
{
    public class SecurityTestClass
    {
        [System.Security.SecurityCritical]
        public void FirstSecurityMethod()
        {
            SecondSecurityMethod();
        }

        [System.Security.SecurityCritical]
        private void SecondSecurityMethod()
        {
            // Assert permissions 

            // do privileged actions, such as method call-outs
        }
    }
}

Community Additions

ADD
Show:
© 2014 Microsoft