[CSHARP-4571] DateOnly serialization not working properly as of 2.19.0 Created: 17/Mar/23  Updated: 10/Jan/24  Resolved: 08/Jan/24

Status: Closed
Project: C# Driver
Component/s: Serialization
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: Ken van Grinsven Assignee: Unassigned
Resolution: Duplicate Votes: 1
Labels: net6
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates CSHARP-3717 Add DateOnly/TimeOnly support Backlog
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

Summary

We have a component that listens to events and saves all properties of the event to a mongo database. We set it up as generic as possible; all properties values are downcast to "object" so they all fit into the same model, which is stored into the database. We noticed that, as of version 2.19.0 which introduced an allowlist for the ObjectSerializer, that storing DateOnly values in a property of type object throws an exception, as the ObjectSerializer says the type is not allowed.

Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

Version 2.19.0.

How to Reproduce

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
var collection1 = database.GetCollection<Test1>("test");
var collection2 = database.GetCollection<Test2>("test");
 
var instance1 = new Test1 { Value = new DateOnly(2022, 1, 1) };
 
var instance2 = new Test2 { Value = new DateOnly(2022, 1, 1) };
 
// Works
await collection1.InsertOneAsync(instance1);
 
// Crashes
await collection2.InsertOneAsync(instance2);
 
public class Test1
{
    public DateOnly Value { get; set; }
}
 
public class Test2
{
    public object Value { get; set; }
}

 

 

Additional Background

Not applicable.



 Comments   
Comment by James Kovacs [ 10/Jan/24 ]

Hi, ken.van.grinsven@zorgmatch.nl,

Thank you for the suggestion. If we compare type name (e.g. System.DateOnly) and assembly name (e.g. System.Runtime.dll), we would open ourselves up to a possible exploit as an attacker could craft their own System.DateOnly type and place it in their own System.Runtime.dll assembly somewhere else on the filesystem. In order to ensure the type is actually the Microsoft-shipped type, we would have to ensure that the containing assembly is signed by Microsoft, which increases the complexity and cost of the check. It is much simpler and secure to use type == typeof(System.DateOnly) once we include a .NET 6+ TFM, which we plan to do in the coming months.

As boris.dogadov@mongodb.com mentioned, please follow CSHARP-3717 for updates.

Sincerely,
James

Comment by Ken van Grinsven [ 09/Jan/24 ]

Hi James, isn't it possible to include System.DateOnly using runtime type checking? Check if a type has name System.DateOnly and check assembly name and such to verify it is the .NET 6 System.DateOnly type?

Comment by Boris Dogadov [ 08/Jan/24 ]

We'll be tracking support of DateOnly and TimeOnly in CSHARP-3717

Comment by James Kovacs [ 20/Mar/23 ]

Hi, ken.van.grinsven@zorgmatch.nl,

Thank you for reporting this issue. 2.19.0 introduced ObjectSerializer.AllowedTypes so that developers could opt into known safe types (CSHARP-4475). The driver includes many known safe types from the base class library including System.DateTime and System.DateTimeOffset.

System.DateOnly is not included in this list because it was introduced in .NET 6. We currently target net472, netstandard2.0, and netstandard2.1. Notably we do not have a net6 TFM because we haven't required it yet. Until we include a net6 TFM in our NuGet package, we have no way of referencing System.DateOnly in the driver itself.

If you are using .NET Core 3.X or newer (including .NET 6), your application will reference the netstandard2.1 TFM. You can reference System.DateOnly in your .NET 6 app and use it to configure ObjectSerializer.AllowedTypes. You should execute code similar to the following as early as possible in your bootstrap process to ensure that your custom-configured ObjectSerializer is registered:

var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type) || type == typeof(System.DateOnly));
BsonSerializer.RegisterSerializer(objectSerializer);

Once we include the net6 TFM, we will be able to add System.DateOnly to our list of default allowed types. Until we are able to do so, the above workaround will allow you to use System.DateOnly with the ObjectSerializer. I will leave this ticket open in our backlog to track the work of implementing support for System.DateOnly once we add the net6 TFM to our driver.

Sincerely,
James

Generated at Wed Feb 07 21:48:38 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.