Securing Method Access

Caution

Code Access Security (CAS) and Partially Trusted Code

The .NET Framework provides a mechanism for the enforcement of varying levels of trust on different code running in the same application called Code Access Security (CAS).

CAS is not supported in .NET Core, .NET 5, or later versions. CAS is not supported by versions of C# later than 7.0.

CAS in .NET Framework should not be used as a mechanism for enforcing security boundaries based on code origination or other identity aspects. CAS and Security-Transparent Code are not supported as a security boundary with partially trusted code, especially code of unknown origin. We advise against loading and executing code of unknown origins without putting alternative security measures in place. .NET Framework will not issue security patches for any elevation-of-privilege exploits that might be discovered against the CAS sandbox.

This policy applies to all versions of .NET Framework, but does not apply to the .NET Framework included in Silverlight.

Some methods might not be suitable to allow arbitrary untrusted code to call. Such methods pose several risks: The method might provide some restricted information; it might believe any information passed to it; it might not do error checking on the parameters; or with the wrong parameters, it might malfunction or do something harmful. You should be aware of these cases and take action to help protect the method.

In some cases, you might need to restrict methods that are not intended for public use but still must be public. For example, you might have an interface that needs to be called across your own DLLs and hence must be public, but you do not want to expose it publicly to prevent customers from using it or to prevent malicious code from exploiting the entry point into your component. Another common reason to restrict a method not intended for public use (but that must be public) is to avoid having to document and support what might be an internal interface.

Managed code offers several ways to restrict method access:

  • Limit the scope of accessibility to the class, assembly, or derived classes, if they can be trusted. This is the simplest way to limit method access. In general, derived classes can be less trustworthy than the class they derive from, though in some cases they share the parent class's identity. In particular, do not infer trust from the keyword protected, which is not necessarily used in the security context.

  • Limit the method access to callers of a specified identity--essentially, any particular evidence (strong name, publisher, zone, and so on) you choose.

  • Limit the method access to callers having whatever permissions you select.

Similarly, declarative security allows you to control inheritance of classes. You can use InheritanceDemand to do the following:

  • Require derived classes to have a specified identity or permission.

  • Require derived classes that override specific methods to have a specified identity or permission.

The following example shows how to help protect a public class for limited access by requiring that callers be signed with a particular strong name. This example uses the StrongNameIdentityPermissionAttribute with a Demand for the strong name. For task-based information on how to sign an assembly with a strong name, see Creating and Using Strong-Named Assemblies.

<StrongNameIdentityPermissionAttribute(SecurityAction.Demand, PublicKey := "…hex…", Name := "App1", Version := "0.0.0.0")>  _
Public Class Class1
End Class
[StrongNameIdentityPermissionAttribute(SecurityAction.Demand, PublicKey="…hex…", Name="App1", Version="0.0.0.0")]
public class Class1
{

}

Excluding Classes and Members from Use by Untrusted Code

Use the declarations shown in this section to prevent specific classes and methods, as well as properties and events, from being used by partially trusted code. By applying these declarations to a class, you apply the protection to all its methods, properties, and events. However, field access is not affected by declarative security. Note also that link demands help protect against only the immediate callers and might still be subject to luring attacks.

Note

A new transparency model has been introduced in the .NET Framework 4. The Security-Transparent Code, Level 2 model identifies secure code with the SecurityCriticalAttribute attribute. Security-critical code requires both callers and inheritors to be fully trusted. Assemblies that are running under the code access security rules from earlier .NET Framework versions can call level 2 assemblies. In this case, the security-critical attributes will be treated as link demands for full trust.

In strong-named assemblies, a LinkDemand is applied to all publicly accessible methods, properties, and events therein to restrict their use to fully trusted callers. To disable this feature, you must apply the AllowPartiallyTrustedCallersAttribute attribute. Thus, explicitly marking classes to exclude untrusted callers is necessary only for unsigned assemblies or assemblies with this attribute; you can use these declarations to mark a subset of types therein that are not intended for untrusted callers.

The following examples show how to prevent classes and members from being used by untrusted code.

For public nonsealed classes:

<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name := "FullTrust"), _
System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name := "FullTrust")>  _
Public Class CanDeriveFromMe
End Class
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public class CanDeriveFromMe
{
}

For public sealed classes:

<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name := "FullTrust")>  _
NotInheritable Public Class CannotDeriveFromMe
End Class
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public sealed class CannotDeriveFromMe
{
}

For public abstract classes:

<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name := "FullTrust"), _
System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name := "FullTrust")>  _
MustInherit Public Class CannotCreateInstanceOfMe_CanCastToMe
End Class
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
public abstract class CannotCreateInstanceOfMe_CanCastToMe {}

For public virtual functions:

Class Base1
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name:="FullTrust"), System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name:="FullTrust")> _
    Public Overridable Sub CanOverrideOrCallMe()
    End Sub 'CanOverrideOrCallMe
End Class 'Base1
class Base1
{
[System.Security.Permissions.PermissionSetAttribute(
System.Security.Permissions.SecurityAction.InheritanceDemand, Name="FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(
System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
    public virtual void CanOverrideOrCallMe() {}
}

For public abstract functions:

MustInherit Class Base2
    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name:="FullTrust"), System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name:="FullTrust")> _
    Public Sub MustOverrideMe()
    End Sub
End Class 'Base2
abstract class Base2 {
[System.Security.Permissions.PermissionSetAttribute(
System.Security.Permissions.SecurityAction.InheritanceDemand, Name = "FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(
System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
public abstract void MustOverrideMe();
}

For public override functions where the base class does not demand full trust:

Class Derived
    Inherits Base1
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Overrides Sub CanOverrideOrCallMe()
        MyBase.CanOverrideOrCallMe()
    End Sub 'CanOverrideOrCallMe
End Class 'Derived
class Derived : Base1
{
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
    public override void CanOverrideOrCallMe()
    {
        base.CanOverrideOrCallMe();
    }
}

For public override functions where the base class demands full trust:

Class Derived
    Inherits Base1
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name:="FullTrust")> _
    Public Overrides Sub CanOverrideOrCallMe()
        MyBase.CanOverrideOrCallMe()
    End Sub 'CanOverrideOrCallMe
End Class 'Derived
class Derived : Base1
{
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
    public override void CanOverrideOrCallMe()
    {
        base.CanOverrideOrCallMe();
    }
}

For public interfaces:

Public Interface ICanCastToMe
    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name:="FullTrust"), System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name:="FullTrust")> _
    Sub CanImplementMe()
End Interface 'ICanCastToMe
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name:="FullTrust"), System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name:="FullTrust")> _
Class Implemented
    Implements ICanCastToMe
    Public Sub CanImplementMe()
    End Sub 'CanImplementMe
public interface ICanCastToMe
{
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name = "FullTrust")]
void CanImplementMe();
}
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")]
[System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name = "FullTrust")]
class Implemented : ICanCastToMe
{
    public void CanImplementMe()
    {
    }
}

Virtual Internal Overrides or Overloads Overridable Friend

Note

This section warns about a security issue when declaring a method as both virtual and internal (Overloads Overridable Friend in Visual Basic). This warning applies only to the .NET Framework versions 1.0 and 1.1, it does not apply to later versions.

In the .NET Framework versions 1.0 and 1.1, you must be aware of a nuance of the type system accessibility when confirming that your code is unavailable to other assemblies. A method that is declared virtual and internal (Overloads Overridable Friend in Visual Basic) can override the parent class's vtable entry and can be used only from within the same assembly because it is internal. However, the accessibility for overriding is determined by the virtual keyword, and this can be overridden from another assembly as long as that code has access to the class itself. If the possibility of an override presents a problem, use declarative security to fix it, or remove the virtual keyword if it is not strictly required.

Even if a language compiler prevents these overrides with a compilation error, it is possible for code written with other compilers to override.

See also