-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BinaryFormatter.Deserialize swallows the SecurityException after #35491 fix. #1733
Comments
It does appear from the docs that SecurityException is special here. |
The What's the particular scenario broken here? Edit: This is akin to the |
Hi guys, thank you for participating. As you know, the So we can have the following environment: [Serializable]
public class UserSettings { /*...*/ } This is how the handling of user settings looks like (this is a sample): try {
// deserializing from some untrusted source
var userSettings = SafeBinaryFormatter<UserSettings>.Deserialize(untrustedBytes);
}
catch(SerializationException) {
// bypass the error, log an issue and continue with unchanged settings
}
catch(System.Security.SecurityException) {
// raise panic and stop the execution
} The sealed class SafeBinaryFormatter<T> {
SafeBinaryFormatter() { }
readonly static BinaryFormatter safeFormatter = new BinaryFormatter() { Binder = new SafeBinder() };
public static T Deserialize(byte[] bytes) {
using(MemoryStream ms = new MemoryStream(bytes))
return (T)safeFormatter.Deserialize(ms);
}
sealed class SafeBinder : SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
if(typeof(T).FullName == typeName && typeof(T).Assembly.FullName == assemblyName)
return typeof(T);
throw new NonTrustedTypeDeserializationException(typeName);
}
}
sealed class NonTrustedTypeDeserializationException : System.Security.SecurityException {
const string messageFormat = "The {0} type is not trusted and therefore is not deserialized due to security reasons.";
internal NonTrustedTypeDeserializationException(string typeName)
: base(string.Format(messageFormat, typeName)) {
}
}
} With the change I mentioned in the context of this issue, the code above is totally broken. Due to them, the real execution flow is changed. Our unit tests are warned about this immediately (we maintain unit tests for all the released and preview environments like .net core 5 in our codebase). Thus it is an important breaking change for us. At the moment, we have to decide whether to add some deep handling of SerializationException on our side or this is a real BC in .net codebase that will be fixed in the release. |
This is not an accurate statement. The Meanwhile I'll mark this as a breaking change so that it bubbles up to the right folks. Thanks for describing your scenario! |
There is nothing incorrect in the documentation and we'll be the happiest developers in the world if our programs work only in a trusted environment. But in the real world, we have to deal with various data from different sources (databases/communication protocols/file formats/external APIs). The solutions like above appear only because we clearly understand all the risks and do our best to guarantee the required security level for our customers. That is why our customers pay for our work ;-)
Happy to hear and will stay tuned, thank you! |
This will be captured in the breaking change document (see dotnet/docs#19604). Thank you for reporting the issue! |
Issue description:
After the source code changes merged in the context of dotnet/corefx#40215 the
BinaryFormatter.Deserialize
method wraps the SecurityException in the SerializationException:Expected Behavior:
According to the documentation the
BinaryFormatter.Deserialize
method must not swallow the SecurityException.To resolve the current issue, you can re-throw the SecurityException:
Affected .Net Version:
.Net Core 5+ (there is no issue in .Net Core 3.1 LTS and below).
The impact: Breaking Change.
This change breaks Securing deserialization with custom SerializationBinder approach.
The text was updated successfully, but these errors were encountered: