Share via


CA2108: Review declarative security on value types

Applies to: yesVisual Studio noVisual Studio for Mac

Note

This article applies to Visual Studio 2017. 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
RuleId CA2108
Category Microsoft.Security
Breaking change Non-breaking

Cause

A public or protected value type is secured by a Data and Modeling or Link Demands.

Note

This rule has been deprecated. For more information, see Deprecated rules.

Rule description

Value types are allocated and initialized by their default constructors before other constructors execute. If a value type is secured by a Demand or LinkDemand, and the caller does not have permissions that satisfy the security check, any constructor other than the default will fail, and a security exception will be thrown. The value type is not deallocated; it is left in the state set by its default constructor. Do not assume that a caller that passes an instance of the value type has permission to create or access the instance.

How to fix violations

You cannot fix a violation of this rule unless you remove the security check from the type, and use method level security checks in its place. Fixing the violation in this manner does not prevent callers with inadequate permissions from obtaining instances of the value type. You must ensure that an instance of the value type, in its default state, does not expose sensitive information, and cannot be used in a harmful manner.

When to suppress warnings

You can suppress a warning from this rule if any caller can obtain instances of the value type in its default state without posing a threat to security.

Example 1

The following example shows a library containing a value type that violates this rule. The StructureManager type assumes that a caller that passes an instance of the value type has permission to create or access the instance.

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

[assembly:AllowPartiallyTrustedCallers]  

namespace SecurityRulesLibrary
{
   // Violates rule: ReviewDeclarativeSecurityOnValueTypes.
   [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]

   public struct SecuredTypeStructure 
   {
      internal double xValue;
      internal double yValue;
      
      public SecuredTypeStructure(double x, double y) 
      {
         xValue = x;
         yValue = y;
         Console.WriteLine("Creating an instance of SecuredTypeStructure.");
      }     
      public override string ToString()
      {
         return String.Format ("SecuredTypeStructure {0} {1}", xValue, yValue);
      }
   }

   public class StructureManager
   {
      // This method asserts trust, incorrectly assuming that the caller must have 
      // permission because they passed in instance of the value type.
      [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Assert, Name="FullTrust")]

      public static SecuredTypeStructure AddStepValue(SecuredTypeStructure aStructure)
      {
         aStructure.xValue += 100;
         aStructure.yValue += 100;
         Console.WriteLine ("New values {0}", aStructure.ToString());
         return aStructure;
      }
   }
}

Example 2

The following application demonstrates the library's weakness.

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using SecurityRulesLibrary;

// Run this test code with partial trust.
[assembly: System.Security.Permissions.PermissionSetAttribute(
   System.Security.Permissions.SecurityAction.RequestRefuse, 
   Name="FullTrust")]

namespace TestSecurityExamples
{
   public class TestDemandOnValueType
   {
      static SecuredTypeStructure mystruct;

      [STAThread]
      public static void Main() 
      {
         try
         {
            mystruct = new SecuredTypeStructure(10,10);
            
         }
         catch (SecurityException e)
         {
            Console.WriteLine(
               "Structure custom constructor: {0}", e.Message);
         }

         // The call to the default constructor 
         // does not throw an exception.
         try 
         {
            mystruct = StructureManager.AddStepValue(
               new SecuredTypeStructure());
         }
         catch (SecurityException e)
         {
            Console.WriteLine(
               "Structure default constructor: {0}", e.Message);
         }

         try 
         {
            StructureManager.AddStepValue(mystruct);
         } 

         catch (Exception e)
         {  
            Console.WriteLine(
               "StructureManager add step: {0}", e.Message);
         }
      }
   }
}

This example produces the following output:

Structure custom constructor: Request failed.
New values SecuredTypeStructure 100 100
New values SecuredTypeStructure 200 200

See also