nuke-build / nuke

🏗 The AKEless Build System for C#/.NET
https://nuke.build
MIT License
2.89k stars 353 forks source link

Migrate away from `BinaryFormatter`? #818

Open tyb-dev opened 2 years ago

tyb-dev commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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>
matkoch commented 2 years ago

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

matkoch commented 2 years ago
var newInstance = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(settingsEntity));
[JsonObjectAttribute(MemberSerialization.Fields)]
class Settings {}
mahranben commented 1 year ago

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

tyb-dev commented 1 year ago

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.

mahranben commented 1 year ago

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 !!

voroninp commented 1 year ago

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
MichaelKetting commented 1 year ago

@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?

cristipufu commented 1 year ago

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

borland commented 9 months ago

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>
Tridy commented 8 months ago

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);
    }
}
MoeHamdan commented 5 months ago

When will this be fixed?

jasontstone commented 5 months ago

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

rogerbriggen-securiton commented 1 month ago

With dotnet 9 Preview 6, BinaryFormatter is gone.

67.29 14:30:09 [ERR] Target Restore has thrown an exception 67.36 System.PlatformNotSupportedException: BinaryFormatter serialization and deserialization have been removed. See https://aka.ms/binaryformatter for more information. 67.36 at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) 67.36 at Nuke.Common.Tooling.SettingsEntityExtensions.NewInstance[T](T settingsEntity) in //source/Nuke.Tooling/SettingsEntity.NewInstance.cs:line 23 67.36 at Nuke.Common.Tools.DotNet.DotNetRestoreSettingsExtensions.SetProjectFile[T](T toolSettings, String projectFile) in //source/Nuke.Common/Tools/DotNet/DotNet.Generated.cs:line 7516

nsentinel commented 1 month ago

@matkoch As a temporary solution, if migration is difficult to .NET 9, you can use the package System.Runtime.Serialization.Formatters (BinaryFormatter has been moved here)

rogerbriggen-securiton commented 1 month ago

@matkoch As a temporary solution, if migration is difficult to .NET 9, you can use the package System.Runtime.Serialization.Formatters (BinaryFormatter has been moved here)

Thanks @nsentinel, that seems to work

nsentinel commented 1 month ago

BinaryFormatter removal from .NET 9 is complete: https://github.com/dotnet/announcements/issues/317

jjaskulowski-configit commented 2 weeks ago

+1 cannot use nuke in net9

nsentinel commented 2 weeks ago

@jjaskulowski-configit As a temporary workaround, you can set .NET 8 target for nuke (_build project), and .NET 9 for everything else. nuke will build such solution fine