CA2147: Transparent methods may not use security asserts
TypeName |
SecurityTransparentCodeShouldNotAssert |
CheckId |
CA2147 |
Category |
Microsoft.Security |
Breaking Change |
Breaking |
Cause
Code that is marked as SecurityTransparentAttribute is not granted sufficient permissions to assert.
Rule Description
This rule analyzes all methods and types in an assembly which is either 100% transparent or mixed transparent/critical, and flags any declarative or imperative usage of Assert.
At run time, any calls to Assert from transparent code will cause a InvalidOperationException to be thrown. This can occur in both 100% transparent assemblies, and also in mixed transparent/critical assemblies where a method or type is declared transparent, but includes a declarative or imperative Assert.
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 application domain. Examples of elevations include Asserts, LinkDemands, SuppressUnmanagedCode, and unsafe code.
How to Fix Violations
To resolve the issue, either mark the code which calls the Assert with the SecurityCriticalAttribute, or remove the Assert.
When to Suppress Warnings
Do not suppress a message from this rule.
Example
This code will fail if SecurityTestClass is transparent, when the Assert method throws a InvalidOperationException.
using System;
using System.Security;
using System.Security.Permissions;
namespace TransparencyWarningsDemo
{
public class TransparentMethodsUseSecurityAssertsClass
{
// CA2147 violation - transparent code using a security assert declaratively. This can be fixed by
// any of:
// 1. Make DeclarativeAssert critical
// 2. Make DeclarativeAssert safe critical
// 3. Remove the assert attribute
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public void DeclarativeAssert()
{
}
public void ImperativeAssert()
{
// CA2147 violation - transparent code using a security assert imperatively. This can be fixed by
// any of:
// 1. Make ImperativeAssert critical
// 2. Make ImperativeAssert safe critical
// 3. Remove the assert call
new PermissionSet(PermissionState.Unrestricted).Assert();
}
}
}
One option is to code review the SecurityTransparentMethod method in the example below, and if the method is considered safe for elevation, mark SecurityTransparentMethod with secure-critical This requires that a detailed, complete, and error-free security audit must be performed on the method together with any call-outs that occur within the method under the Assert:
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
[System.Security.SecurityCritical]
void SecurityCriticalMethod()
{
new FileIOPermission(PermissionState.Unrestricted).Assert();
// perform I/O operations under Assert
}
}
}
Another option is to remove the Assert from the code, and let any subsequent file I/O permission demands flow beyond SecurityTransparentMethod to the caller. This enables security checks. In this case, no security audit is generally needed, because the permission demands will flow to the caller and/or the application domain. Permission demands are closely controlled through security policy, hosting environment, and code-source permission grants.