The Silverlight 2.0 Security Model
Silverlight and the rich client browser
Secure Code By Design
In the .NET Framework, upon loading an assembly the CLR gets evidence for it and figures out the code group of the assembly. A code group defines the list of privileged actions that assemblies are allowed to perform. Whenever some code is about to execute a privileged action, the CLR verifies its permissions and throws if it finds out anything wrong. Permissions for code groups are determined by the machine administrator. The administrator is responsible for defining the security policy for a given machine. In theory, the administrator can also disable code access security altogether. This model of handling security is known as "code access security" (CAS).
At its core, with CAS enabled any method of a .NET Framework class can execute any action unless the assembly it belongs to lacks permissions for it. The Silverlight 2.0 implementation of the CLR (also known as CoreCLR) reverses this principle completely. Any code that goes through the CoreCLR is considered partial trust and is not allowed to call into methods that require higher privileges. The CAS model is not supported in Silverlight 2.0. Code access security in Silverlight 2.0 is guaranteed by a brand new security model.
Security in CoreCLR is based on attributes, as in Table 1.
Any code marked with this attribute runs as partial trust and is not allowed to perform any calls that would elevate the privileges of the call stack. The attribute is supported since version 2.0 of the .NET Framework.
Any code marked with this attribute runs as full-trust and may be called by transparent code. The attribute is new to Silverlight 2.0.
Any code marked with this attribute will always run as full-trust. The attribute is supported since version 2.0 of the .NET Framework.
Table 1: Silverlight 2.0 security attributes.
Each attribute identifies a different level of security hazard associated with the code. The concept of security transparent code is nothing new in the .NET Framework. It refers to code that is marked as unable to call into full-trust code and perform any other action that would possibly elevate the permissions of the call stack. Within the fully-fledged CLR, transparent is only the code that belongs to assemblies explicitly decorated with the SecurityTransparent attribute. Likewise, transparent is also any method or class that is explicitly given the attribute, as below.
public class Foo
public void DoSomething()
Unlike the fully-fledged CLR, in Silverlight 2.0 the CoreCLR considers any code as transparent unless it is decorated with a different security attribute. In particular, this means that all the code in a Silverlight 2.0 application cannot directly execute any critical operations such as invoking unsafe or unverifiable code or attempting system-wide changes through the P/Invoke subsystem. Application code in the Silverlight 2.0 virtual machine runs as partial trust and can only invoke other transparent code or, at most, code marked with the SafeCritical attribute.
What kind of animal is a safe-critical method, class, or assembly? As in Table 1, this attribute doesn't exist in the .NET Framework and has been added just for implementing the Silverlight's security model. The SafeCritical attribute identifies code that sits in between the application code (what users download from the Internet) and the platform code (where some critical methods are defined).
Making Sense of Safe-Critical Code
There are legitimate situations in which the application code may need to execute some pieces of critical code. A fair number of interesting system features are based on critical code. So if you want to give more power to the client, then you must be ready to provide access to some of these APIs. Is this something that can be done securely?
For obvious security reasons, Silverlight doesn't allow application code to call directly into any critical API. The CoreCLR invariably throws a method access exception every time that the application code attempts to call into any critical code. Again, is there a safe way for application code to access critical parts of the operating system? This is exactly where safe-critical code fits in. Have a look at Figure 2.
[Click image to view at full size]
Figure 2: How Silverlight 2.0 processes application code.
Code marked as safe-critical acts a smart proxy towards critical code. Application code is only allowed to call into other transparent and safe code or into code explicitly marked as safe-critical. Safe-critical code is full-trust code that doesn't undergo any sort of limitations. Yet, it plays a key role as it takes the responsibility of enabling risky calls from within application code. Normally, a safe-critical function does a number of checks before passing control to a critical function. Security checks may include parameters validation and any sort of API-specific set of checks aimed at ensuring that the application state is acceptable for the call to continue. Safe-critical methods are a delicate element as they represent the gateway for downloaded application code to access a critical method. How safe is safe-critical code?
SecurityTreatAsSafe vs. SecuritySafeCritical
The SecuritySafeCritical attribute is new to Silverlight 2.0. The concept of code transparency, however, is nothing new in the .NET Framework as the long time existence of some other security attributes demonstrates. This is the case, for example, of the SecurityCritical, SecurityTransparent, and SecurityTreatAsSafe attributes. Why has SecurityTreatAsSafe not been ported to Silverlight and was replaced by SecuritySafeCritical instead?
In the desktop CLR transparency model, all public critical methods are automatically marked as SecurityTreatAsSafe. In the context of Silverlight, a similar setting would enable transparent code to call into any public critical methods, thus severely invalidating the whole security model. For this reason, a new attribute was introduced to instruct the CoreCLR to treat as safe only methods that have been explicitly marked with the attribute.
Application Code and Platform Code
In Figure 2, I assumed that users can only download transparent code. If this assumption is correct, then we can safely conclude that Silverlight 2.0 is a secure environment. In this case, developers can only write transparent code and call into critical methods only via a smart proxy represented by safe-critical methods. But who does provide safe-critical methods? Put another way, is it possible for a developer to inject its own set of safe-critical methods in a Silverlight application? As you understand, this is a decisive point to assess whether Silverlight 2.0 is safe or not.
Silverlight code is partitioned in two families -- application code and platform code. Application code is any custom code that developers write for an application and that users download to their machines. Platform code is all the system code that makes Silverlight run. Application code can only be transparent; any attempt to invoke directly a critical method results in a method access security exception. Platform code can be of any type: transparent, critical or safe-critical; see Figure 2. How do you distinguish between application and platform code?
For the CoreCLR, only code signed with a specific Microsoft public key, and downloaded from a secure location on Microsoft servers, can be considered as platform code and allowed to expose critical or safe-critical entry points. In no way can the CoreCLR be fooled into considering a safety-critical piece of application code. In fact, no code downloaded from a non-Microsoft Web site can be treated as safe-critical and only Microsoft can create safe gateways to access critical APIs within the .NET Framework.
What About Custom Assemblies?
The code of a Silverlight 2.0 application can have dependencies on custom, user-defined assemblies. Not just any assemblies, though. A Silverlight 2.0 project can only add references to other assemblies created as Silverlight class libraries. Existing assemblies that you want to reuse must be recompiled and, if necessary, modified.
The security model in the CoreCLR also enables you to derive new classes only from security transparent classes defined by the platform or your application. A class is considered security transparent if it has no security attribute. It is possible that a platform class is security transparent but contains some safe-critical or critical methods. In this case, you can derive from the class, but you can't override any virtual method that is marked critical. Only transparent or safe-critical virtual methods can be overridden. It should be noted that in a possible override of a safe-critical method, you can't certainly radically alter the implementation of the functionality; or, at least, if you do that, you have to use only security transparent code. Overriding a safe-critical method mostly means that you inject some safe code around the base method implementation. Finally, an application class can only implement security transparent interfaces that don't contain critical methods.
Silverlight 2.0 enables .NET developers to extend their existing skills and investments to build cross-platform rich Internet applications that work in a cross-platform manner and are secure at the root. This article just scratched the surface of code download and security implementation in Silverlight 2.0 applications. Note also that any information discussed in this article is based on a Beta version of the product.