fix: Create appservice devices under the requested device ID (MSC4190) #2028

Merged
ginger merged 1 commit from Deniel9204/continuwuity:fix/2015-msc4190 into main 2026-07-21 13:10:10 +00:00
Contributor

Fixes #2015

The appservice branch of update_device_route (MSC4190 device creation)
generated a random device ID instead of using the one from the request path,
and dropped the requested display name. The PUT returned 200, but the
device the appservice asked for never existed — every subsequent request
masquerading as it failed with M_FORBIDDEN ("Device does not exist for user
or appservice cannot masquerade as this device"), and one orphaned random-ID
device was leaked per attempt.

Combined with the pre-1f5e178c3f behaviour (400 "Token conflicts with an
existing appservice token"), MSC4190 appservice device creation has never
worked end-to-end in any release. On OIDC-enabled servers (where legacy
appservice login is unavailable) this makes encrypted mautrix bridgev2
bridges unable to start.

Tested with mautrix-googlechat (mautrix-go v0.29.0) against a patched build:
MSC4190 device creation lands under the requested ID with the requested
display name, /keys/upload and the restart-time masqueraded /keys/query
both succeed, and the bridge starts with e2be enabled. Curl-only repro from
the issue also passes (PUT a chosen ID → GET returns that ID).

Pull request checklist:

  • This pull request targets the main branch, and the branch is named something other than
    main.
  • I have written an appropriate pull request title and my description is clear.
  • I understand I am responsible for the contents of this pull request.
  • I have followed the [contributing guidelines][c1]:
    • My contribution follows the [code style][c2], if applicable.
    • I ran [pre-commit checks][c1pc] before opening/drafting this pull request.
    • I have [tested my contribution][c1t] (or proof-read it for documentation-only changes)
      myself, if applicable. This includes ensuring code compiles.
    • My commit messages follow the [commit message format][c1cm] and are descriptive.
Fixes #2015 The appservice branch of `update_device_route` (MSC4190 device creation) generated a random device ID instead of using the one from the request path, and dropped the requested display name. The `PUT` returned `200`, but the device the appservice asked for never existed — every subsequent request masquerading as it failed with `M_FORBIDDEN` ("Device does not exist for user or appservice cannot masquerade as this device"), and one orphaned random-ID device was leaked per attempt. Combined with the pre-1f5e178c3f behaviour (400 "Token conflicts with an existing appservice token"), MSC4190 appservice device creation has never worked end-to-end in any release. On OIDC-enabled servers (where legacy appservice login is unavailable) this makes encrypted mautrix bridgev2 bridges unable to start. Tested with mautrix-googlechat (mautrix-go v0.29.0) against a patched build: MSC4190 device creation lands under the requested ID with the requested display name, `/keys/upload` and the restart-time masqueraded `/keys/query` both succeed, and the bridge starts with e2be enabled. Curl-only repro from the issue also passes (PUT a chosen ID → GET returns that ID). **Pull request checklist:** <!-- You need to complete these before your PR can be considered. If you aren't sure about some, feel free to ask for clarification in #dev:continuwuity.org. --> - [X] This pull request targets the `main` branch, and the branch is named something other than `main`. - [X] I have written an appropriate pull request title and my description is clear. - [X] I understand I am responsible for the contents of this pull request. - I have followed the [contributing guidelines][c1]: - [X] My contribution follows the [code style][c2], if applicable. - [X] I ran [pre-commit checks][c1pc] before opening/drafting this pull request. - [X] I have [tested my contribution][c1t] (or proof-read it for documentation-only changes) myself, if applicable. This includes ensuring code compiles. - [X] My commit messages follow the [commit message format][c1cm] and are descriptive.
fix: Use the requested device ID when an appservice creates a device
Some checks failed
Auto Labeler / Apply labels based on changed files (pull_request_target) Successful in 2s
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Check changed files (pull_request) Successful in 5s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 5s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m6s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6m26s
Checks / Prek / Check changed files (push) Successful in 4s
Documentation / Build and Deploy Documentation (push) Successful in 1m6s
Checks / Prek / Pre-commit & Formatting (push) Successful in 1m16s
Checks / Prek / Clippy and Cargo Tests (push) Failing after 6m10s
Release Docker Image / Build linux-amd64 (release) (push) Successful in 12m17s
Release Docker Image / Build linux-arm64 (max-perf) (push) Has been skipped
Release Docker Image / Build linux-arm64 (release) (push) Successful in 11m48s
Release Docker Image / Create Multi-arch Release Manifest (push) Successful in 15s
Release Docker Image / Create Max-Perf Manifest (push) Has been cancelled
Release Docker Image / Release Binaries (push) Has been cancelled
Release Docker Image / Mirror Images (push) Has been cancelled
Release Docker Image / Build linux-amd64 (max-perf) (push) Has been cancelled
25264308ab
The appservice branch of update_device_route (MSC4190 device creation)
generated a random device ID instead of using the one from the request
path, and dropped the requested display name. The PUT returned 200, but
the device the appservice asked for never existed, so every subsequent
request masquerading as that device failed with M_FORBIDDEN and one
orphaned random-ID device was left behind per attempt.

This made encrypted mautrix (bridgev2) bridges unable to start on
OIDC-enabled servers, where MSC4190 is the only available device
creation mechanism: /keys/upload failed on first start and /keys/query
on every restart. Combined with the pre-1f5e178c3f behaviour (400
"Token conflicts with an existing appservice token"), MSC4190 device
creation has never worked end-to-end in any release.

Create the device under the requested ID and forward the requested
display name.
nex approved these changes 2026-07-21 12:38:34 +00:00
nex left a comment

reviewed on my phone but lgtm

reviewed on my phone but lgtm
ginger approved these changes 2026-07-21 13:09:51 +00:00
ginger merged commit 25264308ab into main 2026-07-21 13:10:10 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
continuwuation/continuwuity!2028
No description provided.