Invalid Content-Length header on HTTP/2 204 No Content CORS preflight responses breaks Safari and strict HTTP/2 clients #2965
Replies: 3 comments
-
|
I read through the configuration in the Stalwart documentation for the setup of Stalwart with Traefik. This issue would never be seen when following this setup since the HTTP/s configuration is set up to do TCP pass through directly from the browser through Traefik to the Stalwart Server. So no CORS PreFlight in that situation. This is probably why this issue has not been surfaced prior to now. While the Traefik configuration would obfuscate this issue, it's still something that should be corrected in the code base. |
Beta Was this translation helpful? Give feedback.
-
|
With this issue, I can't use Chrome/Edge/Safari on my iPad to log in. It reported CORS issue when I tried to log in. Please fix....thanks. |
Beta Was this translation helpful? Give feedback.
-
|
Bumping this so it doesn't go stale..... |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Issue Description
When Stalwart handles a CORS OPTIONS preflight request over HTTP/2 (e.g. to /.well-known/jmap or /jmap/session), it returns a 204 No Content response that includes both content-type: application/problem+json and content-length: 78. This violates RFC 7540 §8.1.2.6, which explicitly forbids Content-Length headers on 204 responses over HTTP/2. Strict HTTP/2 clients — including Safari and curl — treat this as a fatal stream error, causing CORS-dependent clients to fail entirely.
Expected Behavior
204 No Content responses must not include a Content-Length header when served over HTTP/2, per RFC 7540 §8.1.2.6. The content-type: application/problem+json header is also incorrect on a 204 with no body — it appears that an error response path sets these headers but then the status code is overridden to 204 without clearing them.
Actual Behavior
Safari fails the CORS preflight silently and reports a cross-origin block to the client application. Firefox tolerates the violation and succeeds, explaining why the issue is browser-specific.
Reproduction Steps
Relevant Log Output
No response
Stalwart Version
v0.15.x
Installation Method
Docker
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
Additional Context
Root cause hypothesis
The CORS OPTIONS handler appears to prepare an RFC 7807 problem+json error response body (78 bytes) but then short-circuits to a 204 status code without clearing the Content-Length and Content-Type headers that were already set. The fix should ensure that any response with status 204 has both headers stripped before the response is written.
This appears to be the offending snippet of code from requests.rs:
Suggested corrections:
or
I acknowledge that:
traceand included relevant log output if applicable.Beta Was this translation helpful? Give feedback.
All reactions