Skip to content

Fix MSC4143: advertise org.matrix.msc4143 in /versions unstable_features#19646

Open
toonbr1me wants to merge 5 commits intoelement-hq:developfrom
toonbr1me:fix/msc4143-unauthenticated-transports-and-versions-flag
Open

Fix MSC4143: advertise org.matrix.msc4143 in /versions unstable_features#19646
toonbr1me wants to merge 5 commits intoelement-hq:developfrom
toonbr1me:fix/msc4143-unauthenticated-transports-and-versions-flag

Conversation

@toonbr1me
Copy link
Copy Markdown

@toonbr1me toonbr1me commented Apr 2, 2026

What does this PR do?

org.matrix.msc4143 was missing from the unstable_features map returned by /_matrix/client/versions when msc4143_enabled: true is set. Every other experimental MSC follows this pattern; MSC4143 was simply missed.

Without this flag, clients have no standard way to discover whether the server supports MSC4143 before calling the endpoint.

The fix adds the flag in line with the existing pattern, along with tests.

Closes #19580

Copilot AI review requested due to automatic review settings April 2, 2026 22:56
@toonbr1me toonbr1me requested a review from a team as a code owner April 2, 2026 22:56
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 2, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes regressions in Synapse’s MSC4143 (MatrixRTC) support by making the RTC transports endpoint usable as a public discovery API and ensuring MSC4143 capability is advertised via /versions.

Changes:

  • Remove authentication requirement from /_matrix/client/unstable/org.matrix.msc4143/rtc/transports.
  • Advertise org.matrix.msc4143 in /versions unstable_features when msc4143_enabled is set.
  • Update/add tests and add a changelog fragment documenting the fixes.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
synapse/rest/client/matrixrtc.py Makes /rtc/transports a public (unauthenticated) discovery endpoint.
synapse/rest/client/versions.py Adds org.matrix.msc4143 to /versions unstable_features.
tests/rest/client/test_matrixrtc.py Updates tests to reflect unauthenticated access expectations.
changelog.d/99999.bugfix Documents the two MSC4143 bugfixes.
Comments suppressed due to low confidence (1)

synapse/rest/client/matrixrtc.py:46

  • Now that this endpoint is intentionally public, returning hs.config.matrix_rtc.transports verbatim increases the risk of accidentally exposing sensitive or irrelevant config keys if an admin misconfigures matrix_rtc.transports (the config model currently accepts an untyped list). Consider sanitizing/validating the response to a strict schema (e.g. whitelist allowed keys per transport type) before returning it.
    async def on_GET(self, request: SynapseRequest) -> tuple[int, JsonDict]:
        # No authentication required: this is a public discovery endpoint.
        # Clients such as Element X call it without a token to determine
        # whether the server supports MatrixRTC before establishing a session.
        if self._transports:
            return 200, {"rtc_transports": self._transports}

        return 200, {}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/rest/client/test_matrixrtc.py Outdated
Comment on lines +63 to +70
@override_config({"experimental_features": {"msc4143_enabled": True}})
def test_matrixrtc_endpoint_requires_authentication(self) -> None:
def test_matrixrtc_endpoint_accessible_without_authentication(self) -> None:
"""The /rtc/transports endpoint is a public discovery endpoint.
Clients use it to check MatrixRTC support before establishing a session,
so it must not require authentication.
"""
channel = self.make_request("GET", f"{PATH_PREFIX}/rtc/transports")
self.assertEqual(401, channel.code, channel.json_body)
self.assertEqual(200, channel.code, channel.json_body)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new unauthenticated-access test only checks the no-transports case (default config). To prevent regressions, add a test that configures at least one matrix_rtc.transports entry and verifies an unauthenticated GET returns 200 and includes that transport (the existing transport-content test currently uses an access token).

Copilot uses AI. Check for mistakes.
Comment thread changelog.d/19646.bugfix Outdated
@@ -0,0 +1 @@
Fix `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` returning 401 for unauthenticated requests. This endpoint is a public discovery endpoint used by clients (e.g. Element X) to check MatrixRTC support before establishing a session. Also advertise `org.matrix.msc4143` in `unstable_features` when `msc4143_enabled` is set.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog fragment filename 99999.bugfix looks like a placeholder rather than the usual issue/PR-number-based naming used elsewhere in changelog.d/ (e.g. 19615.doc, 19633.misc). Rename this fragment to the correct number to avoid collisions and keep towncrier fragments traceable.

Copilot uses AI. Check for mistakes.
Comment on lines 191 to 196
),
# MSC4140: Delayed events
"org.matrix.msc4140": bool(self.config.server.max_event_delay_ms),
# MSC4143: Matrix RTC transports (LiveKit backend)
"org.matrix.msc4143": self.config.experimental.msc4143_enabled,
# Simplified sliding sync
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a new /versions unstable_features flag for MSC4143, but there’s no accompanying test asserting it is false by default and true when experimental_features.msc4143_enabled is set (similar to the existing coverage for org.matrix.msc4140 in tests/rest/client/test_delayed_events.py). Adding a small /versions test would help prevent regressions.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@reivilibre reivilibre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, though not seeing this matching the MSC

# MSC4140: Delayed events
"org.matrix.msc4140": bool(self.config.server.max_event_delay_ms),
# MSC4143: Matrix RTC transports (LiveKit backend)
"org.matrix.msc4143": self.config.experimental.msc4143_enabled,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

org.matrix.msc4143 missing from unstable_features in /versions

Setting msc4143_enabled: true in experimental_features correctly registers the REST endpoint, but the corresponding org.matrix.msc4143 flag was never added to the unstable_features map returned by /_matrix/client/versions. Every other experimental MSC follows the pattern of advertising itself there; MSC4143 was simply missed.

This needs to be fixed in the MSC if desired.
The MSC does not currently prescribe this flag to be added to /versions

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah fair point, the msc’s unstable prefix section doesn't mention this. looks like it just got missed - every other msc does this and without it clients have no way to know if the unstable endpoint exists

i can open a pr on matrix-spec-proposals to add it. do you want me to keep this change here in the meantime or should i pull it out until the msc is updated?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a thread on the MSC matrix-org/matrix-spec-proposals#4143 (comment)

We can see if the author gets back to us

I think it probably makes sense to have one (though it's not an automatic thing for every MSC as it's not always the case)


async def on_GET(self, request: SynapseRequest) -> tuple[int, JsonDict]:
# Require authentication for this endpoint.
await self._auth.get_user_by_req(request)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not seeing in the MSC where it says this should be public, please can you point it out?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey, so the msc doesn't explicitly say "no auth required", but I think the client behaviour makes it pretty clear that's the intent. there's a bunch of people in #19621 who captured their server logs and you can see element x straight up not sending an authorization header for this endpoint #19621 (comment). it's not a bug in the client - it's calling it as a pre-call capability check, before any session is started.

makes sense when you think about it - the section is literally called "Discovery of RTC Transports", and discovery endpoints in matrix are always public (/versions, .well-known, etc). the msc's security section mentions each transport having its own auth - that's about the livekit jwt stuff, not about who can hit the discovery endpoint.

if you'd rather have it spelled out in the msc i can open a pr there too, just lmk

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: just tested this on a live server - upgraded to 1.151.0 (stock, no patches), tried making a call in Element X 26.04.2, and got this in the server logs immediately:

GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports
-> 401 Missing access token
User-Agent: Element X/26.04.2 (Google Pixel 7; Android 17)

call failed instantly. reverted to the patched version, call worked. so this is reproducible on the latest client version too, and .well-known/rtc_foci alone doesn't help - Element X hits this endpoint regardless

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also found matrix-org/matrix-js-sdk#5245 which kinda explains the whole thing - Element Call runs as a widget inside Element X, and RoomWidgetClient just... can't send auth tokens directly, it goes through the widget api instead. so yeah, the endpoint kinda needs to be public by design

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thread on the MSC matrix-org/matrix-spec-proposals#4143 (comment) seems to cover the auth aspect, where there is at least one comment from someone believing it is meant to require authentication.

In my opinion this endpoint should require authentication because the server doesn't want to provide its RTC servers to unauthenticated people.
(This is also why the existing TURN server discovery endpoint requires authentication: https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3voipturnserver)

But I think I will need to ask the MSC author to be doubly sure.

Copy link
Copy Markdown
Contributor

@fkwp fkwp Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See matrix-org/matrix-spec-proposals#4143 (comment)

TL/DR the endpoint requires authentication:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the updated MSC paragraph

matrix-org/matrix-spec-proposals@866ca09

The /_matrix/client/unstable/org.matrix.msc4143/rtc/transports endpoint
was incorrectly requiring authentication. Clients such as Element X
(26.03.3+) call this endpoint without an access token to discover
whether the server supports MatrixRTC before establishing a session.
The 401 response caused these clients to show "call not supported".

Additionally, the org.matrix.msc4143 flag was not being advertised in
the unstable_features map of /_matrix/client/versions, even when
msc4143_enabled was set in experimental_features. This inconsistency
meant clients that check unstable_features (instead of or in addition
to /rtc/transports) would also incorrectly conclude calls are unsupported.

Closes element-hq#19621
Closes element-hq#19580
- Add unauthenticated test with transport data configured
- Add /versions unstable_features test for org.matrix.msc4143
- Rename changelog fragment from 99999.bugfix to 19646.bugfix
@toonbr1me toonbr1me force-pushed the fix/msc4143-unauthenticated-transports-and-versions-flag branch from 9a5a471 to 0415504 Compare April 12, 2026 14:22
@toonbr1me toonbr1me requested a review from reivilibre April 12, 2026 14:59
@toger5
Copy link
Copy Markdown

toger5 commented Apr 13, 2026

For context, this is now fixed in EC:

EC will only use this endpoint (and expects it to be authenticated) if it has an access token:

  /**
   * Fetches the first rtc_foci from the backend.
   * This will not throw errors, but instead just log them and return null if the expected config is not found or malformed.
   * @private
   */
  private async tryBackendTransports(): Promise<LivekitTransportConfig | null> {
    const client = this.client;
    // MSC4143: Attempt to fetch transports from backend.
    // TODO: Workaround for an issue in the js-sdk RoomWidgetClient that
    // is not yet implementing _unstable_getRTCTransports properly (via widget API new action).
    // For now we just skip this call if we are in a widget.
    // In widget mode the client is a `RoomWidgetClient` which has no access token (it is using the widget API).
    // Could be removed once the js-sdk is fixed (https://github.com/matrix-org/matrix-js-sdk/issues/5245)
    const isSPA = !!client.getAccessToken();
    if (isSPA && "_unstable_getRTCTransports" in client) {
      this.logger.info("First try to use getRTCTransports end point ...");
      try {
        const transportList = await doNetworkOperationWithRetry(async () =>
          client._unstable_getRTCTransports(),
        );
        const first = transportList.filter(isLivekitTransportConfig)[0];
        if (first) {
          return first;
        } else {
          this.logger.info(
            `No livekit transport found in getRTCTransports end point`,
            transportList,
          );
        }
      } catch (ex) {
        this.logger.info(`Failed to use getRTCTransports end point: ${ex}`);
      }
    } else {
      this.logger.debug(`getRTCTransports end point not available`);
    }

    return null;
  }

@toonbr1me
Copy link
Copy Markdown
Author

ok makes sense, dropping the auth change after fkwp's comment. didn't realize that was intentional by design
the widget thing is still broken but sounds like that's a js-sdk problem
keeping just the /versions part, will update the description too

toonbr1me and others added 2 commits April 14, 2026 02:32
revert matrixrtc.py to require authentication per MSC4143 design (fkwp confirmed this is intentional). widget mode issue tracked in matrix-org/matrix-js-sdk#5245.

keep the org.matrix.msc4143 unstable_features advertisement in /versions.
@toonbr1me toonbr1me changed the title Fix MSC4143: make /rtc/transports public and advertise in /versions Fix MSC4143: advertise org.matrix.msc4143 in /versions unstable_features Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MSC4143 enabled in experimental_features but missing from unstable_features in /versions endpoint

6 participants