Safe Deserialization
- 3 minutes to read
DevExpress controls use a safety mechanism for all deserialization operations to improve app security. An exception is thrown if a control attempts to load an unsafe type.
Deserialize Trusted Types
You should review all unsafe type exceptions. If you trust a certain exception type, use the following code to enable deserialization:
Call the following method to trust all exception types from a specific assembly:
DevExpress.Utils.DeserializationSettings.RegisterTrustedAssembly("CustomAssembly, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx");
DevExpress.Utils.DeserializationSettings.RegisterTrustedAssembly(typeof(CustomClass).Assembly);
Trust a Section of Your Code
If you trust a data source that raised a given security exception, you can turn off safe deserialization for certain sections of code:
DevExpress.Utils.DeserializationSettings.InvokeTrusted(()=>{
// Trusted deserialization.
// gridView1.RestoreLayoutFromXml(fileName);
});
Resolve Assembly and Data Type Loads
DevExpress UI controls can load assemblies and data types dynamically by calling methods such as Assembly.Load
or Type.GetType()
. Use the DevExpress.Utils.BindToTypePolicy
if you require greater control over assembly/type loading. The policy allows you to inspect assemblies/types and cancel the load operation or type resolution based on a specific condition.
Resolve Unknown Assembly Loads
The policy raises the BindToTypePolicy.QueryAssemblyLoad
event when DevExpress UI controls load assemblies. Handle this event to spot an “unknown” assembly before it is loaded, check its name, and allow or cancel the operation.
The following example demonstrates how to load a specific version from multiple versions of an assembly:
void BindToTypePolicy_QueryAssemblyLoad(object sender, BindToTypePolicy.QueryAssemblyLoadEventArgs e) {
if(e.AssemblyName.StartsWith("EntityFramework", StringComparison.OrdinalIgnoreCase)) {
// Loads a specific assembly version distributed with the application.
var appDirectory = Path.GetDirectoryName(typeof(Program).Assembly.Location);
string path = Path.Combine(appDirectory, @"..\\Lib", "EntityFramework.dll");
e.Assembly = Assembly.LoadFrom(path);
}
}
Event parameters include:
e.AssemblyName
– Gets the assembly name.e.Cancel
– Set this parameter to true to cancel the operation.
Note
You can also call the following methods at application startup to apply a restrictive policy:
BindToTypePolicy.DenyAssemblyLoading
– Prevents dynamic loading of assemblies by DevExpress UI elements.BindToTypePolicy.DenyAssemblyLoadingFromFilesAndBytes
– Prevents DevExpress UI controls from loading assemblies from arbitraty paths and Byte arrays (Assembly.LoadFile(String)
,Assembly.Load(Byte[])
).
Resolve Unknown Data Types
Handle the BindToTypePolicy.QueryBindToType
event to spot dynamic loading of a type, check its name and assembly, and allow the type resolve operation. The policy fires this event every time DevExpress UI controls call the Type.GetType()
method.
void BindToTypePolicy_QueryBindToType(object sender, BindToTypePolicy.QueryBindToTypeEventArgs e) {
if(!e.IsKnownType) {
// Resolves custom datasource types for DevExpress Reports.
if(e.TypeName == "ProductsJsonDataSource")
e.Type = typeof(ProductsJsonDataSource);
if(e.TypeName == "UsersJsonDataSource")
e.Type = typeof(UsersJsonDataSource);
}
}
Event parameters include:
e.IsKnownType
– Gets whether the type is whitelisted (the type is safe).e.Type
– Gets or sets the type. Use this parameter to resolve the type.e.TypeName
– Gets the type name.e.Assembly
– Gets the assembly that contains the processed type.e.AssemblyName
– Gets the assembly name.e.AssemblyQualifiedTypeName
– Gets the assembly-qualified name of the type, which includes the name of the assembly from which thisType
object is being loaded.e.Cancel
– Set this parameter to true to cancel type resolution.
Note
Handle the BindToTypePolicy.QueryNonTrustedTypeValidation
event to validate blacklisted and “unknown” types. The policy does not fire this event to whitelisted/trusted types.
static void BindToTypePolicy_QueryNonTrustedTypeValidation(object sender, BindToTypePolicy.QueryNonTrustedTypeValidationEventArgs e) {
if(e.IsUnsafe)
throw new MyAppLicationSecurityException(e.AssemlyQualifiedTypeName);
if(e.AssemblyName == typeof(Program).Assembly.FullName)
e.TrustThisType();
if(e.TypeName == "ObsoleteJsonDataSource")
e.DoNotTrustThisType();
}
Example: How to Log Assembly/Type Loads
void BindToTypePolicy_QueryAssemblyLoad(object sender, BindToTypePolicy.QueryAssemblyLoadEventArgs e) {
Console.WriteLine(e.ToString());
}
void BindToTypePolicy_QueryBindToType(object sender, BindToTypePolicy.QueryBindToTypeEventArgs e) {
Console.WriteLine(e.ToString());
}