Why BinaryFormatter Was Deprecated in Modern C
Binary serialization converts complex in-memory object graphs into a
compact stream of bytes for storage or network transport. For years,
BinaryFormatter was the standard implementation in the .NET
ecosystem, prized for its ability to serialize entire object graphs,
including private fields and cyclical references, with minimal
configuration. However, Microsoft has completely deprecated and disabled
BinaryFormatter in modern .NET (.NET 7, 8, and 9) because
it possesses critical, unfixable security vulnerabilities that allow
remote code execution, alongside tight runtime coupling that limits
cross-platform interoperability.
What Is Binary Serialization?
Binary serialization is the process of mapping an application's in-memory object state directly into a compact binary format. Unlike text-based formats like JSON or XML, binary representations omit human-readable formatting, whitespace, and structural delimiters.
In early .NET implementations, binary serialization captured not only an object's public properties but also its exact runtime type definitions, assembly versions, private fields, and complex reference graphs. This made it effortless to save and restore complex object structures without writing custom mapping logic or defining strict data contracts.
Why BinaryFormatter Was Deprecated
Despite its convenience, BinaryFormatter contains
foundational architectural choices that make it hazardous in modern
distributed environments.
Inherent Remote Code Execution (RCE) Vulnerabilities
The primary reason for the deprecation of
BinaryFormatter is security. BinaryFormatter
deserializes payloads by reading type metadata directly embedded inside
the incoming byte stream. When it instantiates these types, it
automatically invokes constructors, finalizers, or specialized
deserialization callbacks before the consuming application can validate
the data.
Attackers exploit this mechanism by injecting carefully crafted "gadget chains"—sequences of standard .NET framework classes present in the application's runtime. When instantiated or finalized during deserialization, these gadget chains can execute arbitrary system commands, bypass security controls, and compromise the host machine.
Impossibility of Remediation
Microsoft determined that BinaryFormatter cannot be
secured against deserialization attacks. Traditional mitigation
techniques, such as using custom SerializationBinder
implementations to whitelist safe types, routinely fail because:
- Gadget chains continuously evolve as new framework libraries and dependencies are discovered.
- The deserializer needs access to generic framework types that can be leveraged to circumvent validation logic.
- Vulnerabilities exist at the architectural level rather than as isolated implementation bugs.
Because the component was designed to trust the incoming stream
implicitly, the official guidance states that
BinaryFormatter should never be used with untrusted data,
and no patch can make it safe.
Versioning and Cross-Platform Incompatibilities
BinaryFormatter deeply ties serialized payloads to
specific .NET internal types, assembly versions, and namespaces. A
change to a private field name or an update to a framework assembly
version often invalidates previously serialized data. Furthermore,
because it relies on .NET-specific runtime characteristics, it offers
virtually no interoperability with applications written in other
programming languages.
Phased Removal in Modern .NET
Due to these architectural risks, Microsoft progressively phased out
BinaryFormatter:
- .NET 5 and .NET 6: Marked the API as obsolete with compilation warnings and introduced runtime switches to disable it.
- .NET 7 and .NET 8: Deprecated the component by default in most project templates and disabled it in ASP.NET Core applications.
- .NET 9: Completely removed the implementation from
the shared framework runtime, causing
BinaryFormattermethods to throw aPlatformNotSupportedExceptionunless legacy compatibility packages are explicitly forced.
Modern, Secure Alternatives
Applications relying on BinaryFormatter must migrate to
modern serialization frameworks that separate data from behavioral
logic:
- System.Text.Json: The default, high-performance JSON serializer built into modern .NET. It uses explicit data contracts and does not deserialize arbitrary types by default, eliminating code-execution exploits.
- Protocol Buffers (protobuf-net): A contract-based binary format developed by Google that produces compact payloads, provides rapid serialization speeds, and supports cross-language environments.
- MessagePack: An efficient binary format that mirrors JSON data models but provides the performance and payload size advantages of binary data.
- MemoryPack: A high-speed, zero-encoding binary serializer specifically optimized for modern C# that avoids polymorphic deserialization vulnerabilities through compile-time code generation.