CA2107: Review deny and permit only usage

Note

This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here

Item Value
TypeName ReviewDenyAndPermitOnlyUsage
CheckId CA2107
Category Microsoft.Security
Breaking Change Breaking

Cause

A method contains a security check that specifies the PermitOnly or Deny security action.

Rule Description

The Using the PermitOnly Method and System.Security.CodeAccessPermission.Deny security actions should be used only by those who have an advanced knowledge of .NET Framework security. Code that uses these security actions should undergo a security review.

Deny alters the default behavior of the stack walk that occurs in response to a security demand. It lets you specify permissions that must not be granted for the duration of the denying method, regardless of the actual permissions of the callers in the call stack. If the stack walk detects a method that is secured by Deny, and if the demanded permission is included in the denied permissions, the stack walk fails. PermitOnly also alters the default behavior of the stack walk. It allows code to specify only those permissions that can be granted, regardless of the permissions of the callers. If the stack walk detects a method that is secured by PermitOnly, and if the demanded permission is not included in the permissions that are specified by the PermitOnly, the stack walk fails.

Code that relies on these actions should be carefully evaluated for security vulnerabilities because of their limited usefulness and subtle behavior. Consider the following:

  • Link Demands are not affected by Deny or PermitOnly.

  • If the Deny or PermitOnly occurs in the same stack frame as the demand that causes the stack walk, the security actions have no effect.

  • Values that are used to construct path-based permissions can usually be specified in multiple ways. Denying access to one form of the path does not deny access to all forms. For example, if a file share \\Server\Share is mapped to a network drive X:, to deny access to a file on the share, you must deny \\Server\Share\File, X:\File and every other path that accesses the file.

  • An System.Security.CodeAccessPermission.Assert can terminate a stack walk before the Deny or PermitOnly is reached.

  • If a Deny has any effect, namely, when a caller has a permission that is blocked by the Deny, the caller can access the protected resource directly, bypassing the Deny. Similarly, if the caller does not have the denied permission, the stack walk would fail without the Deny.

How to Fix Violations

Any use of these security actions will cause a violation. To fix a violation, do not use these security actions.

When to Suppress Warnings

Suppress a warning from this rule only after you complete a security review.

Example

The following example demonstrates some limitations of Deny.

The following library contains a class that has two methods that are identical except for the security demands that protect them.

using System.Security;
using System.Security.Permissions;
using System;

namespace SecurityRulesLibrary
{
   public  class SomeSecuredMethods
   {
    
      // Demand immediate caller has suitable permission
      // before revealing sensitive data.
      [EnvironmentPermissionAttribute(SecurityAction.LinkDemand,
          Read="COMPUTERNAME;USERNAME;USERDOMAIN")]

      public static void MethodProtectedByLinkDemand()
      {
         Console.Write("LinkDemand: ");
      }

      [EnvironmentPermissionAttribute(SecurityAction.Demand,
          Read="COMPUTERNAME;USERNAME;USERDOMAIN")]

      public static void MethodProtectedByDemand()
      {
         Console.Write("Demand: ");
      }
   }
}

Example

The following application demonstrates the effects of Deny on the secured methods from the library.

using System.Security;
using System.Security.Permissions;
using System;
using SecurityRulesLibrary;

namespace TestSecurityLibrary
{
    // Violates rule: ReviewDenyAndPermitOnlyUsage.
   public class TestPermitAndDeny
   {
      public static void TestAssertAndDeny()
      {
         EnvironmentPermission envPermission = new EnvironmentPermission(
               EnvironmentPermissionAccess.Read,
               "COMPUTERNAME;USERNAME;USERDOMAIN");
         envPermission.Assert();
         try
         {
            SomeSecuredMethods.MethodProtectedByDemand();
            Console.WriteLine(
               "Caller's Deny has no effect on Demand " + 
               "with the asserted permission.");

            SomeSecuredMethods.MethodProtectedByLinkDemand();
            Console.WriteLine(
               "Caller's Deny has no effect on LinkDemand " + 
               "with the asserted permission.");
         }
         catch (SecurityException e)
         {
            Console.WriteLine(
               "Caller's Deny protected the library.{0}", e);
         }
      }

      public static void TestDenyAndLinkDemand()
      {
         try
         {
            SomeSecuredMethods.MethodProtectedByLinkDemand();
            Console.WriteLine(
               "Caller's Deny has no effect with " +
               "LinkDemand-protected code.");
         }
         catch (SecurityException e)
         {
            Console.WriteLine(
               "Caller's Deny protected the library.{0}",e);
         }
      }
         
      public static void Main()
      {
         EnvironmentPermission envPermission = new EnvironmentPermission(
            EnvironmentPermissionAccess.Read,
            "COMPUTERNAME;USERNAME;USERDOMAIN");
         envPermission.Deny();

         //Test Deny and Assert interaction for LinkDemands and Demands.
         TestAssertAndDeny();

         //Test Deny's effects on code in different stack frame. 
         TestDenyAndLinkDemand();

         //Test Deny's effect on code in same frame as deny.
         try
         {
            SomeSecuredMethods.MethodProtectedByLinkDemand();
            Console.WriteLine(
               "This Deny has no effect with LinkDemand-protected code.");
         }
         catch (SecurityException e)
         {
            Console.WriteLine("This Deny protected the library.{0}",e);
         }
      }
   }
}

This example produces the following output.

Demand: Caller's Deny has no effect on Demand with the asserted permission. LinkDemand: Caller's Deny has no effect on LinkDemand with the asserted permission. LinkDemand: Caller's Deny has no effect with LinkDemand-protected code. LinkDemand: This Deny has no effect with LinkDemand-protected code.

See Also

System.Security.CodeAccessPermission.PermitOnly System.Security.CodeAccessPermission.Assert System.Security.CodeAccessPermission.Deny System.Security.IStackWalk.PermitOnly Secure Coding Guidelines Overriding Security Checks Using the PermitOnly Method