/_matrix/client/v3/account/whoami returns 404 M_NOT_FOUND instead of 403 M_FORBIDDEN #1195

Open
opened 2025-11-23 20:16:23 +00:00 by JasonGantner · 2 comments

The whoami endpoint is apparently not compliant with the current spec.

From what I gathered, the server must not differentiate between a user that doesn't exist and a user that is not allowed for the appservice.

For context, this bug is blocking mautrix-telegram because it checks for its bot user at startup before actually registering it and stops as soon as it encounters the 404 instead of a 403 (see mautrix-telgram!999).

The `whoami` endpoint is apparently not compliant with the [current spec](https://spec.matrix.org/v1.16/client-server-api/#get_matrixclientv3accountwhoami). From what I gathered, the server must not differentiate between a user that doesn't exist and a user that is not allowed for the appservice. For context, this bug is blocking mautrix-telegram because it checks for its bot user at startup before actually registering it and stops as soon as it encounters the 404 instead of a 403 (see [mautrix-telgram!999](https://github.com/mautrix/telegram/issues/999)).
Owner

Looks like a check just needs implementing here:

Ok(whoami::v3::Response {
user_id: body.sender_user().to_owned(),
device_id: body.sender_device.clone(),
is_guest: services.users.is_deactivated(body.sender_user()).await?
&& body.appservice_info.is_none(),
})

something like if body.sender_user.is_none() {Err!(Request(Forbidden("...")))} or whatever.

Looks like a check just needs implementing here: https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/7e4071c1178c07cb6c1b6eefbbbc26d7cff8d065/src/api/client/account.rs#L711-L716 something like `if body.sender_user.is_none() {Err!(Request(Forbidden("...")))}` or whatever.
Owner

Having the check implicit like it is there is very questionable, but this particular affect can be fixed by swapping the condition:

	is_guest: body.appservice_info.is_none()
			&& services
				.users
				.is_deactivated(body.sender_user())
				.await?,

In that case the branch will be short-circuited and appservices will never reach it. Checking if the user exists can happen before that, withservices.users.exists - and appservices (or maybe admin API in future) should be thoe only ones able to reach whoami on unreachable users.

Having the check implicit like it is there is very questionable, but this particular affect can be fixed by swapping the condition: ```rs is_guest: body.appservice_info.is_none() && services .users .is_deactivated(body.sender_user()) .await?, ``` In that case the branch will be short-circuited and appservices will never reach it. Checking if the user exists can happen before that, with`services.users.exists` - and appservices (or maybe admin API in future) should be thoe only ones able to reach whoami on unreachable users.
Sign in to join this conversation.
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#1195
No description provided.