nuke icon indicating copy to clipboard operation
nuke copied to clipboard

Migrate away from `BinaryFormatter`?

Open tyb-dev opened this issue 2 years ago • 14 comments

Usage Information

6.0.0-beta0001

Relevant Code / Invocations

Nuke.Common.Tooling.SettingsEntityExtensions.NewInstance

Expected Behavior

No exception

What actually happened?

Exception while using Docker Nuke wrapper

Stacktrace / Log

System.NotSupportedException: BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information.
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream , Object )
   at Nuke.Common.Tooling.SettingsEntityExtensions.NewInstance[T](T settingsEntity)
   at Nuke.Common.Tools.Docker.DockerLoginSettingsExtensions.SetUsername[T](T toolSettings, String username)
   at Build.<get_Login>b__11_5(DockerLoginSettings s) in /src/Apps/DebianPipeline/Build.cs:line 56
   at Nuke.Common.Tools.Docker.DockerTasks.DockerLogin(Configure`1 configurator)
   at Build.<get_Login>b__11_4() in /src/Apps/DebianPipeline/Build.cs:line 56
   at Nuke.Common.Execution.BuildExecutor.<>c.<Execute>b__4_2(Action x)
   at Nuke.Common.Utilities.Collections.EnumerableExtensions.ForEach[T](IEnumerable`1 enumerable, Action`1 action)
   at Nuke.Common.Execution.BuildExecutor.Execute(NukeBuild build, ExecutableTarget target, IReadOnlyCollection`1 previouslyExecutedTargets, Boolean failureMode)

Anything else we should know?

BinaryFormatters are prohibited under certain circumstances. Although this usage within SettingsEntityExtensions arguably has no security implications, the BinaryFormatter might not be available generally for the entire app, which restricts usage of Nuke.

https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete

tyb-dev avatar Dec 01 '21 13:12 tyb-dev

It's more a limitation than a bug, but it's not exactly a new feature either, which is why I created a bug.

tyb-dev avatar Dec 01 '21 13:12 tyb-dev

I used .NET 6.0 and I have the following properties in my csproj, which might influence the situation.

	<PublishSingleFile>true</PublishSingleFile>
	<SelfContained>true</SelfContained>
	<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
	<PublishReadyToRun>true</PublishReadyToRun>
	<PublishTrimmed>true</PublishTrimmed>

tyb-dev avatar Dec 01 '21 13:12 tyb-dev

Just a heads-up: I crossed this before too and plan to replace with JSON serialization.

matkoch avatar Feb 10 '22 21:02 matkoch

var newInstance = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(settingsEntity));
[JsonObjectAttribute(MemberSerialization.Fields)]
class Settings {}

matkoch avatar Jun 07 '22 21:06 matkoch

It's more a limitation than a bug, but it's not exactly a new feature either, which is why I created a bug.

@tyb-dev have you found a workaround ? I have the same problem with a selfcontained I tried <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> and noWarn but still does not work for me

mahranben avatar Jun 25 '23 22:06 mahranben

It's more a limitation than a bug, but it's not exactly a new feature either, which is why I created a bug.

@tyb-dev have you found a workaround ? I have the same problem with a selfcontained I tried true and noWarn but still does not work for me

Not without changing Nuke itself.

tyb-dev avatar Jun 26 '23 15:06 tyb-dev

It's more a limitation than a bug, but it's not exactly a new feature either, which is why I created a bug.

@tyb-dev have you found a workaround ? I have the same problem with a selfcontained I tried true and noWarn but still does not work for me

Not without changing Nuke itself.

I managed to workaround it by disabling "PublishTrimmed". It's twice as big as my ordinary binary but that should do it for now until the change is made. Thanks !!

mahranben avatar Jun 26 '23 15:06 mahranben

In .NET 8 preview docker Restore step throws.

https://learn.microsoft.com/en-us/dotnet/core/compatibility/serialization/8.0/binaryformatter-disabled

Starting in .NET 8, the affected methods throw a NotSupportedException at run time across all project types except Windows Forms and WPF. The APIs continue to remain obsolete (as error) across all project types, including Windows Forms and WPF.

[ERR] Target Restore has thrown an exception
System.NotSupportedException: BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information.
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at Nuke.Common.Tooling.SettingsEntityExtensions.NewInstance[T](T settingsEntity) in /_/source/Nuke.Common/Tooling/SettingsEntity.NewInstance.cs:line 22
at Nuke.Common.Tools.DotNet.DotNetRestoreSettingsExtensions.SetProjectFile[T](T toolSettings, String projectFile) in /_/source/Nuke.Common/Tools/DotNet/DotNet.Generated.cs:line 6526
at Build.<get_Restore>b__7_2(DotNetRestoreSettings _) in /build/build/Build.cs:line 45
at Nuke.Common.Tools.DotNet.DotNetTasks.DotNetRestore(Configure`1 configurator) in /_/source/Nuke.Common/Tools/DotNet/DotNet.Generated.cs:line 361
at Build.<get_Restore>b__7_1() in /build/build/Build.cs:line 45
at Nuke.Common.Execution.BuildExecutor.<>c.<Execute>b__4_2(Action x) in /_/source/Nuke.Common/Execution/BuildExecutor.cs:line 112
at Nuke.Common.Utilities.Collections.EnumerableExtensions.ForEach[T](IEnumerable`1 enumerable, Action`1 action) in /_/source/Nuke.Common/Utilities/Collections/Enumerable.ForEach.cs:line 17
at Nuke.Common.Execution.BuildExecutor.Execute(NukeBuild build, ExecutableTarget target, IReadOnlyCollection`1 previouslyExecutedTargets, Boolean failureMode) in /_/source/Nuke.Common/Execution/BuildExecutor.cs:line 112

voroninp avatar Aug 07 '23 21:08 voroninp

@voroninp you can use <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> for the build project.

@matkoch just a head's up: starting with .NET 9, binary serialization will be removed (according to the current roadmap). Is this something where a contribution would help / be feasiable?

MichaelKetting avatar Aug 11 '23 08:08 MichaelKetting

Please take a look: https://github.com/nuke-build/nuke/pull/1247

cristipufu avatar Aug 31 '23 10:08 cristipufu

Workaround taken from https://github.com/nuke-build/nuke/issues/1282 which has been closed as a duplicate of this bug:

Add this to your Nuke project's csproj file:

<PropertyGroup>
   .. other existing properties ...
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>

borland avatar Nov 20 '23 04:11 borland

Would something like this solve it?


[PublicAPI]
public static partial class SettingsEntityExtensions
{
    public static T NewInstance<T>(this T settingsEntity)
        where T : ISettingsEntity
    {
        T newInstance = DeepCopyWithJson(settingsEntity);
        if (newInstance is ToolSettings toolSettings)
        {
            toolSettings.ProcessArgumentConfigurator = ((ToolSettings) (object) settingsEntity).ProcessArgumentConfigurator;
            toolSettings.ProcessLogger = ((ToolSettings) (object) settingsEntity).ProcessLogger;
            toolSettings.ProcessExitHandler = ((ToolSettings) (object) settingsEntity).ProcessExitHandler;
        }

        return newInstance;
    }
    
    public static T DeepCopyWithJson<T>(T obj) where T: ISettingsEntity
    {
        string json = JsonSerializer.Serialize(obj);
        return JsonSerializer.Deserialize<T>(json);
    }
}

Tridy avatar Jan 15 '24 09:01 Tridy

When will this be fixed?

MoeHamdan avatar Mar 22 '24 12:03 MoeHamdan

The EnableUnsafeBinaryFormatterSerialization workaround is not working on at least the latest .NET 8 SDK, so a fix would be really appreciated.

jasontstone avatar Apr 02 '24 20:04 jasontstone