Canonicalise media server-name comparisons¶
- Status: accepted
- Date: 2026-10-06
Technical Story: 2026-09-29 security audit finding MED-5.
Context and Problem Statement¶
The media repository routes download and thumbnail requests to either the local store or a remote fetch based on a string comparison of the request's serverName with the configured local server name. Matrix server names are case-insensitive in practice and the default federation port :8448 is optional; treating EXAMPLE.ORG:8448 as remote causes the homeserver to fetch its own media over federation, leaking local-only media IDs and wasting bandwidth.
Decision Drivers¶
- Routing must treat case and default-port variants of the local server as local.
- Only variants that name the same server may be merged.
example.org:8449andexample.orgare different Matrix server names. - Remote media must still be fetched when the server name is genuinely different.
Considered Options¶
- Compare raw request
serverNameagainstruntime.config.server().server_nameunchanged. - Normalise by lower-casing the host and stripping
:8448before comparison. - Normalise with
federation::strip_server_port, which drops any numeric port. - Resolve both sides through the full server discovery pipeline before deciding local vs remote.
Decision Outcome¶
Chosen option: "Normalise by lower-casing the host and stripping :8448 before comparison", because it is the minimal normalisation that closes the routing leak. Option 3 was the first implementation and is rejected: it treats example.org:8449 as this server and serves local media under another server's mxc:// URI. strip_server_port suits server ACLs, which match host names only, not server identity. Full discovery is unnecessary for the local-vs-remote decision and would add network latency and failure modes to a path that should be strictly local.
Positive Consequences¶
- Requests for
Example.ORG,example.org:8448, etc., now serve local media directly. - A request naming another port on the same host is still treated as remote.
Negative Consequences¶
-
The audit also recommended rejecting discovery results that resolve to this server's own listener. That is not implemented. A self-fetch cannot loop, because the federation media endpoint serves local media only and remote fetching is off by default (
security.media.remote_fetch_enabled), but it still costs one outbound request. -
A non-standard port other than
:8448is not stripped; operators using custom federation ports must still supply the matching port in client requests.
Links¶
- Related security-audit report:
docs/security-audit-report-2026-09-29.mdfinding MED-5.