fix: address argus review on matrix admin-room reset — ascii lowercase, tighter markers, unit tests

This commit is contained in:
atlas 2026-06-04 15:05:01 +02:00 committed by mara
commit 97a78cc5d6

View file

@ -354,14 +354,20 @@ async fn discover_admin_room_id(
/// Try to parse the new password from an admin-room bot response.
/// Conduwuit/tuwunel responds with a message like:
/// "Done: Password of user @user:server has been reset. The new password is: <password>"
///
/// Uses [`str::to_ascii_lowercase`] for case folding — unlike `to_lowercase`,
/// ASCII lowercasing is guaranteed to produce a same-byte-length string, so the
/// byte offset from `find` is always a valid index into the original `bot_message`
/// and we never slice at a non-char boundary.
fn extract_new_password(bot_message: &str) -> Option<String> {
// Look for "new password is:" (case-insensitive) followed by whitespace + the password.
let lower = bot_message.to_lowercase();
// ASCII lowercase: same byte length as the original, so positions from
// `lower.find(marker)` are valid byte indices into `bot_message`.
let lower = bot_message.to_ascii_lowercase();
for marker in &[
"new password is: ",
"new password is:",
"password is: ",
"password: ",
"password is:",
] {
if let Some(pos) = lower.find(marker) {
let rest = &bot_message[pos + marker.len()..];
@ -378,6 +384,53 @@ fn extract_new_password(bot_message: &str) -> Option<String> {
None
}
#[cfg(test)]
mod extract_new_password_tests {
use super::extract_new_password;
#[test]
fn tuwunel_style_response() {
let msg = "Done: Password of user @atlas:pr1ma.darkest.space has been reset. The new password is: abc123XYZ!";
assert_eq!(extract_new_password(msg).as_deref(), Some("abc123XYZ!"));
}
#[test]
fn case_insensitive_marker() {
let msg = "Password reset complete. New Password Is: S3cr3tP@ss";
assert_eq!(extract_new_password(msg).as_deref(), Some("S3cr3tP@ss"));
}
#[test]
fn marker_without_trailing_space() {
let msg = "new password is:hunter2";
assert_eq!(extract_new_password(msg).as_deref(), Some("hunter2"));
}
#[test]
fn shorter_marker_variant() {
let msg = "Your password is: Tr0ub4dor&3";
assert_eq!(extract_new_password(msg).as_deref(), Some("Tr0ub4dor&3"));
}
#[test]
fn no_match_returns_none() {
let msg = "Command not recognised. Please try again.";
assert_eq!(extract_new_password(msg), None);
}
#[test]
fn empty_after_marker_returns_none() {
let msg = "new password is: ";
assert_eq!(extract_new_password(msg), None);
}
#[test]
fn password_stops_at_whitespace() {
let msg = "New password is: abc123 (save it now)";
assert_eq!(extract_new_password(msg).as_deref(), Some("abc123"));
}
}
/// Reset a user's password via the Matrix admin room as a fallback for
/// homeservers that do not implement the Synapse admin REST API (e.g.
/// tuwunel 1.6.x). Sends `reset-password @<localpart>:<server>` to