Evaluating BinaryFormatter Security in C#: What You Need to Know

Serialization is a fundamental concept in C#, allowing developers to convert objects into a format that can be stored or transmitted and later reconstructed. BinaryFormatter, a built-in .NET serialization mechanism, has been widely used for this purpose. However, it comes with serious security risks that make it unsuitable for modern application development.

In this article, we will evaluate the security concerns associated with BinaryFormatter, discuss why Microsoft discourages its use, and explore secure alternatives that should be used instead.

What is BinaryFormatter?

BinaryFormatter is a class in the System.Runtime.Serialization.Formatters.Binary namespace that provides a way to serialize and deserialize objects into a binary format. It is commonly used for:

  • Storing object states

  • Transmitting objects across application domains

  • Caching data

A simple example of using BinaryFormatter looks like this:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        Person person = new Person { Name = "John Doe", Age = 30 };
        BinaryFormatter formatter = new BinaryFormatter();

        using (FileStream fs = new FileStream("person.dat", FileMode.Create))
        {
            formatter.Serialize(fs, person);
        }

        using (FileStream fs = new FileStream("person.dat", FileMode.Open))
        {
            Person deserializedPerson = (Person)formatter.Deserialize(fs);
            Console.WriteLine($"Deserialized: {deserializedPerson.Name}, {deserializedPerson.Age}");
        }
    }
}

While BinaryFormatter appears convenient, it introduces significant security vulnerabilities.

Security Risks of BinaryFormatter

1. Arbitrary Code Execution

One of the most critical risks of BinaryFormatter is arbitrary code execution. Because deserialization reconstructs an object graph, malicious actors can craft payloads that execute arbitrary code when deserialized.

Example exploit scenario:

  • An attacker crafts a malicious object graph.

  • The application deserializes it using BinaryFormatter.

  • Code execution occurs within the application context, leading to Remote Code Execution (RCE).

2. Lack of Control Over Deserialization

Unlike System.Text.Json or XmlSerializer, BinaryFormatter does not allow developers to enforce strict type control, making it susceptible to deserialization attacks where attackers inject unexpected objects that compromise security.

3. .NET 5 and Later: Marked as Obsolete

Microsoft has deprecated BinaryFormatter in .NET 5 and later due to these security concerns. The official recommendation is to avoid using BinaryFormatter altogether and migrate to safer alternatives.

Safer Alternatives to BinaryFormatter

1. System.Text.Json (Recommended for JSON)

The System.Text.Json namespace in .NET Core and .NET 5+ is the preferred way to serialize and deserialize JSON securely.

Example:

using System;
using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        Person person = new Person { Name = "Jane Doe", Age = 25 };
        string jsonString = JsonSerializer.Serialize(person);
        Console.WriteLine(jsonString);

        Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
        Console.WriteLine($"Deserialized: {deserializedPerson.Name}, {deserializedPerson.Age}");
    }
}

2. XmlSerializer (For XML-Based Serialization)

If XML is needed, XmlSerializer is a safe alternative that supports type control.

Example:

using System;
using System.IO;
using System.Xml.Serialization;

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        Person person = new Person { Name = "Alice", Age = 28 };
        XmlSerializer serializer = new XmlSerializer(typeof(Person));

        using (StringWriter writer = new StringWriter())
        {
            serializer.Serialize(writer, person);
            Console.WriteLine(writer.ToString());
        }
    }
}

3. MessagePack (For High-Performance Serialization)

MessagePack is a compact, high-performance binary serialization format that is safer than BinaryFormatter.

Example:

using System;
using MessagePack;

[MessagePackObject]
public class Person
{
    [Key(0)] public string Name { get; set; }
    [Key(1)] public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        Person person = new Person { Name = "Bob", Age = 35 };
        byte[] bytes = MessagePackSerializer.Serialize(person);
        Person deserializedPerson = MessagePackSerializer.Deserialize<Person>(bytes);
        Console.WriteLine($"Deserialized: {deserializedPerson.Name}, {deserializedPerson.Age}");
    }
}

Best Practices for Secure Serialization in .NET

  1. Avoid BinaryFormatter – It is deprecated and insecure.

  2. Use System.Text.Json for JSON – It is the recommended serialization format for modern .NET applications.

  3. Whitelist Allowed Types – If deserialization is necessary, restrict the types that can be deserialized.

  4. Enable Security Policies – Apply serialization policies that enforce strict type safety.

  5. Avoid Deserializing Untrusted Data – Never deserialize data from unknown or unverified sources.

  6. Use Secure Formats – Consider MessagePack or Protobuf for compact and secure serialization.

Conclusion

BinaryFormatter has been a widely used serialization mechanism in .NET, but its security vulnerabilities make it a dangerous choice. Microsoft strongly discourages its use, and developers should migrate to safer alternatives like System.Text.Json, XmlSerializer, or MessagePack. Following best practices for secure serialization will help protect applications from deserialization attacks and ensure data integrity.

By adopting secure serialization methods, C# developers can build more resilient, secure, and modern applications in the .NET ecosystem.