Problem / Motivation
I noticed the docs for the telemetry say it checks the server header on /.well-known/jmap for stalwart_version.
Looking at the code it just reads it and checks using regex
|
const res = await fetch(wellKnown, { |
|
method: 'GET', |
|
signal: AbortSignal.timeout(3000), |
|
}); |
|
const server = res.headers.get('server') ?? ''; |
|
const m = server.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/); |
|
const version = m?.[1] ?? null; |
Many reverse proxies setups will strip or replace server headers.
The regex is also too permissive "nginx/1.29.3".match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/)[1] is 1.29.3 for example.
So I think this would be polluted with versions of reverse proxies.
More importantly at least in my config Stalwart doesn't return a Server header.
Response Headers
curl -L localhost:8080/.well-known/jmap -v
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:8080...
* Connected to localhost (::1) port 8080
* using HTTP/1.x
> GET /.well-known/jmap HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 307 Temporary Redirect
< cache-control: no-cache
< location: /jmap/session
< content-length: 0
< date: Tue, 29 Apr 2026 00:00:00 GMT
* Ignoring the response-body
* setting size while ignoring
<
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/jmap/session'
* Re-using existing http: connection with host localhost
> GET /jmap/session HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< content-length: 1292
< date: Tue, 29 Apr 2026 00:00:00 GMT
<
So I don't think there will be any valid responses unless this is something I turned off and forgot. Looking at the response from .well-known/jmap I think the closest thing to a version is the json value capabilities["urn:ietf:params:jmap:sieve"]["implementation"] but that's not really the same as the stalwart version.
Proposed Solution
I'm not sure what a solution is as the exact information doesn't appear to be available without authentication. Assuming capabilities["urn:ietf:params:jmap:sieve"]["implementation"] will be updated based on capabilities that could be reasonable alternative.
Alternatives Considered
No response
Feature Area
Other
Mockups / Examples
No response
Additional Context
No response
Problem / Motivation
I noticed the docs for the telemetry say it checks the server header on
/.well-known/jmapforstalwart_version.Looking at the code it just reads it and checks using regex
webmail/lib/telemetry/payload.ts
Lines 106 to 112 in fc49fe0
Many reverse proxies setups will strip or replace server headers.
The regex is also too permissive
"nginx/1.29.3".match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/)[1]is 1.29.3 for example.So I think this would be polluted with versions of reverse proxies.
More importantly at least in my config Stalwart doesn't return a Server header.
Response Headers
So I don't think there will be any valid responses unless this is something I turned off and forgot. Looking at the response from
.well-known/jmapI think the closest thing to a version is the json valuecapabilities["urn:ietf:params:jmap:sieve"]["implementation"]but that's not really the same as the stalwart version.Proposed Solution
I'm not sure what a solution is as the exact information doesn't appear to be available without authentication. Assuming
capabilities["urn:ietf:params:jmap:sieve"]["implementation"]will be updated based on capabilities that could be reasonable alternative.Alternatives Considered
No response
Feature Area
Other
Mockups / Examples
No response
Additional Context
No response