{"id":1183,"date":"2024-08-28T17:42:23","date_gmt":"2024-08-28T17:42:23","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2024\/08\/28\/binaryformatter-removed-from-net-9\/"},"modified":"2024-08-28T17:42:23","modified_gmt":"2024-08-28T17:42:23","slug":"binaryformatter-removed-from-net-9","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2024\/08\/28\/binaryformatter-removed-from-net-9\/","title":{"rendered":"BinaryFormatter removed from .NET 9"},"content":{"rendered":"<p>Starting with .NET 9, we no longer include an implementation of<br \/>\nBinaryFormatter in the runtime (.NET Framework remains unchanged). The APIs<br \/>\nare still present, but their implementation always throws an exception,<br \/>\nregardless of project type. Hence, setting the existing backwards compatibility<br \/>\nflag is no longer sufficient to use BinaryFormatter.<\/p>\n<p>In this blog post, I\u2019ll explain why this change was made and what options you<br \/>\nhave to move forward.<\/p>\n<h2>TL;DR: What should I do?<\/h2>\n<p>You have two options to address the removal of BinaryFormatter\u2018s<br \/>\nimplementation:<\/p>\n<p><strong>Migrate away from BinaryFormatter<\/strong>. We strongly recommend that you<br \/>\ninvestigate options to stop using BinaryFormatter due to the associated<br \/>\nsecurity risks. The <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/\">BinaryFormatter migration guide<\/a> lists<br \/>\nseveral options.<br \/>\n<strong>Keep using BinaryFormatter<\/strong>. If you need to continue using<br \/>\nBinaryFormatter in .NET 9, you need to depend on the unsupported<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/compatibility-package\">System.Runtime.Serialization.Formatters<\/a> NuGet package,<br \/>\nwhich restores the unsafe legacy functionality and replaces the throwing implementation.<\/p>\n<div class=\"alert alert-primary\">\n<p><strong>Note<\/strong><\/p>\n<p>Please note that .NET Framework is unaffected by this change and continues to include an implementation of BinaryFormatter. However, we still strongly recommend to stop using BinaryFormatter from .NET Framework too, for the same reasons.<\/p><\/div>\n<h2>What\u2019s the risk in using BinaryFormatter?<\/h2>\n<p>Any deserializer, binary or text, that allows its input to carry information<br \/>\nabout the objects to be created is a security problem waiting to happen. There<br \/>\nis a common weakness enumeration (CWE) that describes the issue: <a href=\"https:\/\/cwe.mitre.org\/data\/definitions\/502.html\">CWE-502<br \/>\n\u201cDeserialization of Untrusted Data\u201d<\/a>. BinaryFormatter, included in the<br \/>\nthe initial release of .NET Framework in 2002, is such a deserializer. We also<br \/>\ncover this in the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-security-guide\">BinaryFormatter security guide<\/a>.<\/p>\n<h2>Why we removed BinaryFormatter<\/h2>\n<p>We strongly believe that .NET should make it easy for customers to do the right<br \/>\nthing and hard, if not impossible, to do the wrong thing. We generally refer to<br \/>\nthis as the \u201cpit of success\u201d.<\/p>\n<p>Shipping a technology that is widely regarded as unsafe is counter to this goal.<br \/>\nAt the same time, we also have a responsibility to ensure customers can support<br \/>\nand move their existing code forward. We can\u2019t just remove widely used<br \/>\ncomponents from a .NET release, even when communicated long in advance. We also<br \/>\nneed a migration plan and stop gap options.<\/p>\n<p>This removal was not a sudden change. Due to the known risks of using<br \/>\nBinaryFormatter, we excluded it from .NET Core 1.0. But without a clear<br \/>\nmigration path to using something safer, customer demand led to<br \/>\nBinaryFormatter being included in .NET Core 2.0.<\/p>\n<p>Since then, we have been on the path to removing BinaryFormatter, slowly<br \/>\nturning it off by default in multiple project types but letting consumers opt-in<br \/>\nvia flags if still needed for backward compatibility:<\/p>\n<p><a href=\"https:\/\/github.com\/dotnet\/designs\/blob\/main\/accepted\/2020\/better-obsoletion\/binaryformatter-obsoletion.md\">2020: BinaryFormatter Obsoletion Plan<\/a><br \/>\n<a href=\"https:\/\/github.com\/dotnet\/announcements\/issues\/284\">2023: .NET 8 Update<\/a>: Implementation throws by default<br \/>\n<a href=\"https:\/\/github.com\/dotnet\/announcements\/issues\/293\">2024: .NET 9 Update<\/a>: Announced intention of removal early in the release cycle<br \/>\n<a href=\"https:\/\/github.com\/dotnet\/announcements\/issues\/317\">2024: .NET 9 Update<\/a>: Removal completed<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/compatibility\/serialization\/9.0\/binaryformatter-removal\">2024: .NET 9 Breaking Change<\/a>: In-box BinaryFormatter implementation removed and always throws<\/p>\n<p>In .NET 9 we removed all remaining in-box dependencies on BinaryFormatter and<br \/>\nreplaced the implementation with one that always throws.<\/p>\n<h2>Options to move forward<\/h2>\n<p>New code should not take a dependency on BinaryFormatter. For existing code,<br \/>\nyou should first investigate alternatives to BinaryFormatter. In case you<br \/>\ndon\u2019t control the serializer but only perform deserialization, you can consider<br \/>\nonly reading the BinaryFormatter payload, without performing any<br \/>\ndeserialization. And if none of this works for you can bring the implementation<br \/>\nback by depending on an (unsupported) <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/compatibility-package\">compatibility package<\/a>.<\/p>\n<p>I\u2019ll explore these options in more detail below.<\/p>\n<h3>Migrate-Away<\/h3>\n<p>You should first investigate whether you can replace BinaryFormatter with<br \/>\nanother serializer. We have four recommendations:<\/p>\n<p><strong>Text-based<\/strong>. If a binary serialization format is not a requirement, you can<br \/>\nconsider using JSON or XML serialization formats. These serializers are<br \/>\nincluded in .NET and are supported by us.<\/p>\n<p><a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/migrate-to-system-text-json\">JSON using\u202fSystem.Text.Json<\/a><br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/migrate-to-datacontractserializer\">XML using\u202fSystem.Runtime.Serialization.DataContractSerializer<\/a><\/p>\n<p><strong>Binary<\/strong> If a compact binary representation is important for your scenarios,<br \/>\nthe following serialization formats and open-source serializers are<br \/>\nrecommended:<\/p>\n<p><a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/migrate-to-messagepack\">MessagePack\u202fusing\u202fMessagePack for C#<\/a><br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/migrate-to-protobuf-net\">Protocol Buffers\u202fusing\u202fprotobuf-net<\/a><\/p>\n<p>Since DataContractSerializer honors the same attribute and interface as<br \/>\nBinaryFormatter (namely [Serializable] and ISerializable), it\u2019s probably<br \/>\nthe easiest one to migrate to. If your migration goals include adopting a<br \/>\nmodern and performant serializer or a format with better cross-platform<br \/>\ninteroperability, the other options should be considered.<\/p>\n<h3>Read BinaryFormatter Payloads<\/h3>\n<p>If your code doesn\u2019t control the serialization but only the deserialization (for<br \/>\nuse the new <a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/system.formats.nrbf.nrbfdecoder\">NrbfDecoder<\/a> to <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/read-nrbf-payloads\">read BinaryFormatter<br \/>\npayloads<\/a>. This allows you to read the encoded data without any<br \/>\ndeserialization. It\u2019s the equivalent of using a JSON\/XML reader without the<br \/>\ndeserializer:<\/p>\n<p>using System.Formats.Nrbf;<\/p>\n<p>void Read(Stream payload)<br \/>\n{<br \/>\n    SerializationRecord rootObject = NrbfDecoder.Decode(payload);<\/p>\n<p>    if (rootObject is PrimitiveTypeRecord primitiveRecord)<br \/>\n    {<br \/>\n        Console.WriteLine($&#8221;It was a primitive value: &#8216;{primitiveRecord.Value}'&#8221;);<br \/>\n    }<br \/>\n    else if (rootObject is ClassRecord classRecord)<br \/>\n    {<br \/>\n        Console.WriteLine($&#8221;It was a class record of &#8216;{classRecord.TypeName.AssemblyQualifiedName}&#8217; type name.&#8221;);<br \/>\n    }<br \/>\n    else if (rootObject is SZArrayRecord&lt;byte&gt; arrayOfBytes)<br \/>\n    {<br \/>\n        Console.WriteLine($&#8221;It was an array of `{arrayOfBytes.Length}`-many bytes.&#8221;);<br \/>\n    }<br \/>\n}<\/p>\n<p>For more details, check out the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/read-nrbf-payloads\">Nrbf documentation<\/a>.<\/p>\n<h3>BinaryFormatter compatibility package<\/h3>\n<p>If you have explored the options and determined you can\u2019t migrate away from<br \/>\nBinaryFormatter, you can also install the unsupported<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/compatibility-package\">System.Runtime.Serialization.Formatters<\/a> NuGet package and set the<br \/>\ncompatibility switch to true:<\/p>\n<p>&lt;PropertyGroup&gt;<br \/>\n  &lt;TargetFramework&gt;net9.0&lt;\/TargetFramework&gt;<br \/>\n  &lt;EnableUnsafeBinaryFormatterSerialization&gt;true&lt;\/EnableUnsafeBinaryFormatterSerialization&gt;<br \/>\n&lt;\/PropertyGroup&gt;<\/p>\n<p>&lt;ItemGroup&gt;<br \/>\n  &lt;PackageReference Include=&#8221;System.Runtime.Serialization.Formatters&#8221; Version=&#8221;9.0.0&#8243; \/&gt;<br \/>\n&lt;\/ItemGroup&gt;<\/p>\n<p>The package replaces the in-box implementation of BinaryFormatter with a<br \/>\nfunctioning one, including its vulnerabilities and risks. It\u2019s meant as a<br \/>\nstopgap if you can\u2019t wait with migrating to .NET 9 while not having replaced the<br \/>\nusages of BinaryFormatter yet.<\/p>\n<p>Since the BinaryFormatter API still exists and this package only replaces the<br \/>\nin-box implementation you only need to reference it from application projects.<br \/>\nExisting code that is compiled against BinaryFormatter will continue to work.\n<\/p>\n<div class=\"alert alert-danger\">\n<p><strong>Caution<\/strong><\/p>\n<p>The compatibility package is not supported and unsafe. We strongly recommend<br \/>\nagainst taking a dependency on this package and to instead migrate away from<br \/>\nBinaryFormatter.<\/p><\/div>\n<h2>Summary<\/h2>\n<p>Since the start of .NET Core we have been on a path of deprecating<br \/>\nBinaryFormatter, due to <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-security-guide\">its security risks<\/a>.<\/p>\n<p>Starting with .NET 9, we no longer ship an implementation with the runtime. We<br \/>\nrecommend that you <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/\">migrate away from BinaryFormatter<\/a>. If that<br \/>\ndoesn\u2019t work for you can either start <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/read-nrbf-payloads\">reading the binary payloads without<br \/>\ndeserializing<\/a> or you can take a dependency on the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/standard\/serialization\/binaryformatter-migration-guide\/compatibility-package\">unsupported<br \/>\ncompatibility package<\/a>.<\/p>\n<p>The post <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/binaryformatter-removed-from-dotnet-9\/\">BinaryFormatter removed from .NET 9<\/a> appeared first on <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\">.NET Blog<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Starting with .NET 9, we no longer include an implementation of BinaryFormatter in the runtime (.NET Framework remains unchanged). The [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7],"tags":[],"class_list":["post-1183","post","type-post","status-publish","format-standard","hentry","category-dotnet"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=1183"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1183\/revisions"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=1183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=1183"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=1183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}