dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.07k stars 9.9k forks source link

Setting the SignalR JSON encoder to JavaScriptEncoder.Default does not have any effect #56419

Open jdbrock opened 1 month ago

jdbrock commented 1 month ago

Is there an existing issue for this?

Describe the bug

I've noticed that setting the JSON encoder of a SignalR hub to JavaScriptEncoder.Default does not have the desired effect of escaping certain characters. The output seems to be the same as when using UnsafeRelaxedJsonEscaping.

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddSignalR()
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.Encoder = JavaScriptEncoder.Default;
    });

var app = builder.Build();
app.MapHub<PersonHub>("/person");
app.Run();

This is what's being produced by the SignalR hub:

{"firstName":"Joey","lastName":"<script>alert('Bad Guy');</script>"}

Confirmed that this is what is being sent over the wire (via Fiddler):

2024-06-24 10_06_18-Progress Telerik Fiddler Classic

Expected Behavior

I would expect the output to be as follows:

{"FirstName":"Joey","LastName":"\u003Cscript\u003Ealert(\u0027Bad Guy\u0027);\u003C/script\u003E"}

Steps To Reproduce

https://github.com/jdbrock/SignalREncodingRepro

Exceptions (if any)

No response

.NET Version

8.0.302

Anything else?

No response

BrennanConroy commented 1 month ago

The problem is that the encoder from PayloadSerializerOptions doesn't get used when calling the JsonSerializer.Serialize(ref writer, ..., payloadSerializerOptions) overload. The options from the writer get used instead.

However, when looking at fixing this, I realized that while it would change what gets sent over the wire, the end result on both the .NET and Javascript side is that exact same string. You don't get an escaped string. So not sure how useful it would be to fix this if the only result is more bytes over the wire.