CA2112: Secured types should not expose fields

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 SecuredTypesShouldNotExposeFields
CheckId CA2112
Category Microsoft.Security
Breaking Change Breaking

Cause

A public or protected type contains public fields and is secured by a Link Demands.

Rule Description

If code has access to an instance of a type that is secured by a link demand, the code does not have to satisfy the link demand to access the type's fields.

How to Fix Violations

To fix a violation of this rule, make the fields nonpublic and add public properties or methods that return the field data. LinkDemand security checks on types protect access to the type's properties and methods. However, code access security does not apply to fields.

When to Suppress Warnings

Both for security issues and for good design, you should fix violations by making the public fields nonpublic. You can suppress a warning from this rule if the field does not hold information that should remain secured, and you do not rely on the contents of the field.

Example

The following example is composed of a library type (SecuredTypeWithFields) with unsecured fields, a type (Distributor) that can create instances of the library type and mistaken passes instances to types do not have permission to create them, and application code that can read an instance's fields even though it does not have the permission that secures the type.

The following library code violates the rule.

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

namespace SecurityRulesLibrary
{
   // This code requires immediate callers to have full trust.
   [System.Security.Permissions.PermissionSetAttribute(
       System.Security.Permissions.SecurityAction.LinkDemand, 
       Name="FullTrust")]
   public class SecuredTypeWithFields 
   {
      // Even though the type is secured, these fields are not.
      // Violates rule: SecuredTypesShouldNotExposeFields.
      public double xValue;
      public double yValue;
      
      public SecuredTypeWithFields (double x, double y) 
      {
         xValue = x;
         yValue = y;
         Console.WriteLine(
            "Creating an instance of SecuredTypeWithFields.");
      }
      public override string ToString()
      {
          return String.Format (
            "SecuredTypeWithFields {0} {1}", xValue, yValue);
      }
   }
}

Example

The application cannot create an instance because of the link demand that protects the secured type. The following class enables the application to obtain an instance of the secured type.

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

// This assembly executes with full trust. 

namespace SecurityRulesLibrary
{
   // This type creates and returns instances of the secured type.
   // The GetAnInstance method incorrectly gives the instance 
   // to a type that does not have the link demanded permission.

   public class Distributor
   {
      static SecuredTypeWithFields s = new SecuredTypeWithFields(22,33);
      public static SecuredTypeWithFields GetAnInstance ()
      {
            return s;
      }

      public static void DisplayCachedObject ()
      {
         Console.WriteLine(
            "Cached Object fields: {0}, {1}", s.xValue , s.yValue);
      }
   }
}

Example

The following application illustrates how, without permission to access a secured type's methods, code can access its fields.

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

// This code executes with partial trust.
[assembly: System.Security.Permissions.PermissionSetAttribute(
   System.Security.Permissions.SecurityAction.RequestRefuse,
   Name = "FullTrust")]
namespace TestSecurityExamples
{
    public class TestLinkDemandOnField
    {
        [STAThread]
        public static void Main()
        {
            // Get an instance of the protected object.
            SecuredTypeWithFields secureType = Distributor.GetAnInstance();

            // Even though this type does not have full trust,
            // it can directly access the secured type's fields.
            Console.WriteLine(
               "Secured type fields: {0}, {1}",
               secureType.xValue,
               secureType.yValue);
            Console.WriteLine("Changing secured type's field...");
            secureType.xValue = 99;

            // Distributor must call ToString on the secured object.
            Distributor.DisplayCachedObject();

            // If the following line is uncommented, a security 
            // exception is thrown at JIT-compilation time because 
            // of the link demand for full trust that protects 
            // SecuredTypeWithFields.ToString().

            // Console.WriteLine("Secured type {0}",secureType.ToString());
        }
    }
}

This example produces the following output.

Creating an instance of SecuredTypeWithFields. Secured type fields: 22, 33 Changing secured type's field... Cached Object fields: 99, 33

CA1051: Do not declare visible instance fields

See Also

Link Demands Data and Modeling