When sending a request to Kestrel web server with header value which has non standard ASCII characters, the server rejects the response with 400 Bad request: malformed headers.
Steps to reproduce the behavior:
This is reproducible with 2.1.9, 2.1.10 and 2.2.4
wget -Uri http://localhost:5000 -Headers @{"test"="Tk'eml煤ps te Secw茅pemc"}
The request is accepted and the header value is accessible in the Request.Headers
.NET Core SDK (reflecting any global.json):
Version: 2.2.203
Commit: e5bab63eca
Runtime Environment:
OS Name: Windows
OS Version: 10.0.17763
OS Platform: Windows
RID: win10-x64
Base Path: C:Program Filesdotnetsdk2.2.203
Host (useful for support):
Version: 2.2.4
Commit: f95848e524
.NET Core SDKs installed:
2.1.505 [C:Program Filesdotnetsdk]
2.1.603 [C:Program Filesdotnetsdk]
2.2.106 [C:Program Filesdotnetsdk]
2.2.203 [C:Program Filesdotnetsdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.9 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.10 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.4 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.9 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.10 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.4 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.9 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 2.1.10 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 2.2.4 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Forgot to mention that when using IIS/IISExpress, inproc mode accepts the header while the default out of proc doesn't (as 'expected'...)
@JunTaoLuo / @Tratcher
What is the expected behaviour here? You know I believe rejecting the headers is the correct default, with an option to accept invalid and possibly dangerous input being left as opt-in, for all hosts.
UTF-8 sent directly to Kestrel should work. No other encodings are accepted. We'd want a wireshark trace to verify the encoding.
If you send UTF-8 through IIS out-of-proc the encoding gets messed up and rejected.
Note the UTF-8 support was added in 2.2 (https://github.com/aspnet/KestrelHttpServer/issues/1144). That's the only version we need to investigate.
@Tratcher here's the Wireshark trace. IIS is not involved.
0050 48 54 54 50 2f 31 2e 31 0d 0a 74 65 73 74 3a 20 HTTP/1.1..test:
0060 54 6b 27 65 6d 6c fa 70 73 20 74 65 20 53 65 63 Tk'eml.ps te Sec
0070 77 e9 70 65 6d 63 0d 0a 55 73 65 72 2d 41 67 65 w.pemc..User-Age
0080 6e 74 3a 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 nt: Mozilla/5.0
That's not UTF-8, it's ANSII. 煤 is encoded as fa. In UTF-8 it would be \xC3\xBA.
I tried the following headers, all didn't return 400, but the value was read as is from ctx.request.headers:
wget -Uri http://localhost:5000 -Headers @{"test"="\x54\x6b\x27\x65\x6d\x6c\xc3\xba\x70\x73\x20\x74\x65\x20\x53\x65\x63\x77\xc3\xa9\x70\x65\x6d\x63"; "Accept-Charset"="UTF-8"}
wget -Uri http://localhost:5000 -Headers @{"test"="\x54\x6b\x27\x65\x6d\x6c\xc3\xba\x70\x73\x20\x74\x65\x20\x53\x65\x63\x77\xc3\xa9\x70\x65\x6d\x63"}
wget -Uri http://localhost:5000 -Headers @{"test"="Tk'eml\xC3\xBAps te Secw\xC3\xBApemc"; "Accept-Charset"="UTF-8"}
Wireshark? Are you sure it's not sending the literal string \x54 rather than the byte 54?
Any idea how to force sending a byte array instead of a string as the header value?
No, very few clients let you control the header encoding.
Is there a way to inject custom code before Kestrel rejects the request, or I must have a reverse proxy in front of it?
A reverse proxy is your best option.
Ok, thanks, I'll get working on that. It would be nice if the server was a little more lenient in this, or at least allows interjection. This exact set up is working with IIS in proc mode as well as other web servers. Unfortunately Kesterl is the only container hosting option ATM.
Closing as per the discussion. Kestrel requires the use of UTF-8 or ASCII, ANSI extensions are not supported. Either use a client that sends UTF-8, or use a reverse proxy that transcodes this.
Most helpful comment
Ok, thanks, I'll get working on that. It would be nice if the server was a little more lenient in this, or at least allows interjection. This exact set up is working with IIS in proc mode as well as other web servers. Unfortunately Kesterl is the only container hosting option ATM.