CA2118: Review SuppressUnmanagedCodeSecurityAttribute usage
Item | Value |
---|---|
RuleId | CA2118 |
Category | Microsoft.Security |
Breaking change | Breaking |
Cause
A public or protected type or member has the System.Security.SuppressUnmanagedCodeSecurityAttribute attribute.
Note
This rule has been deprecated. For more information, see Deprecated rules.
Rule description
SuppressUnmanagedCodeSecurityAttribute changes the default security system behavior for members that execute unmanaged code using COM interop or platform invocation. Generally, the system makes a Data and Modeling for unmanaged code permission. This demand occurs at run time for every invocation of the member, and checks every caller in the call stack for permission. When the attribute is present, the system makes a Link Demands for the permission: the permissions of the immediate caller are checked when the caller is just-in-time (JIT)-compiled.
This attribute is primarily used to increase performance; however, the performance gains come with significant security risks. If you place the attribute on public members that call native methods, the callers in the call stack (other than the immediate caller) do not need unmanaged code permission to execute unmanaged code. Depending on the public member's actions and input handling, it might allow untrustworthy callers to access functionality normally restricted to trustworthy code.
.NET relies on security checks to prevent callers from gaining direct access to the current process's address space. Because this attribute bypasses normal security, your code poses a serious threat if it can be used to read or write to the process's memory. Note that the risk is not limited to methods that intentionally provide access to process memory; it is also present in any scenario where malicious code can achieve access by any means, for example, by providing surprising, malformed, or invalid input.
The default security policy does not grant unmanaged code permission to an assembly unless it is executing from the local computer or is a member of one of the following groups:
My Computer Zone Code Group
Microsoft Strong Name Code Group
ECMA Strong Name Code Group
How to fix violations
Carefully review your code to ensure that this attribute is absolutely necessary. If you are unfamiliar with managed code security, or do not understand the security implications of using this attribute, remove it from your code. If the attribute is required, you must ensure that callers cannot use your code maliciously. If your code does not have permission to execute unmanaged code, this attribute has no effect and should be removed.
When to suppress warnings
To safely suppress a warning from this rule, you must ensure that your code does not provide callers access to native operations or resources that can be used in a destructive manner.
Example 1
The following example violates the rule.
using System.Security;
// These two classes are identical
// except for the location of the attribute.
namespace SecurityRulesLibrary
{
public class MyBadMemberClass
{
[SuppressUnmanagedCodeSecurityAttribute()]
public void DoWork()
{
FormatHardDisk();
}
void FormatHardDisk()
{
// Code that calls unmanaged code.
}
}
[SuppressUnmanagedCodeSecurityAttribute()]
public class MyBadTypeClass
{
public void DoWork()
{
FormatHardDisk();
}
void FormatHardDisk()
{
// Code that calls unmanaged code.
}
}
}
Example 2
In the following example, the DoWork
method provides a publicly accessible code path to the platform invocation method FormatHardDisk
.
using System.Security;
using System.Runtime.InteropServices;
namespace SecurityRulesLibrary
{
public class SuppressIsOnPlatformInvoke
{
// The DoWork method is public and provides unsecured access
// to the platform invoke method FormatHardDisk.
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("native.dll")]
private static extern void FormatHardDisk();
public void DoWork()
{
FormatHardDisk();
}
}
// Having the attribute on the type also violates the rule.
[SuppressUnmanagedCodeSecurityAttribute()]
public class SuppressIsOnType
{
[DllImport("native.dll")]
private static extern void FormatHardDisk();
public void DoWork()
{
FormatHardDisk();
}
}
}
Example 3
In the following example, the public method DoDangerousThing
causes a violation. To resolve the violation, DoDangerousThing
should be made private, and access to it should be through a public method secured by a security demand, as illustrated by the DoWork
method.
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace SecurityRulesLibrary
{
[SuppressUnmanagedCodeSecurityAttribute()]
public class BadTypeWithPublicPInvokeAndSuppress
{
[DllImport("native.dll")]
public static extern void DoDangerousThing();
public void DoWork()
{
// Note that because DoDangerousThing is public, this
// security check does not resolve the violation.
// This only checks callers that go through DoWork().
SecurityPermission secPerm = new SecurityPermission(
SecurityPermissionFlag.ControlPolicy |
SecurityPermissionFlag.ControlEvidence
);
secPerm.Demand();
DoDangerousThing();
}
}
}