diff --git a/crates/checksums/src/lib.rs b/crates/checksums/src/lib.rs index 3f06520ba..3117a6275 100644 --- a/crates/checksums/src/lib.rs +++ b/crates/checksums/src/lib.rs @@ -349,7 +349,7 @@ mod tests { fn base64_encoded_checksum_to_hex_string(header_value: &HeaderValue) -> String { let decoded_checksum = base64::decode(header_value.to_str().unwrap()).unwrap(); let decoded_checksum = decoded_checksum.into_iter().fold(String::new(), |mut acc, byte| { - write!(acc, "{byte:02X?}").expect("string will always be writeable"); + write!(acc, "{byte:02X?}").expect("string will always be writable"); acc }); diff --git a/rustfs/src/admin/handlers/group.rs b/rustfs/src/admin/handlers/group.rs index 63a59ee24..5db394645 100644 --- a/rustfs/src/admin/handlers/group.rs +++ b/rustfs/src/admin/handlers/group.rs @@ -25,6 +25,7 @@ use crate::{ use http::{HeaderMap, StatusCode}; use hyper::Method; use matchit::Params; +use percent_encoding::percent_decode_str; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_credentials::get_global_action_cred; use rustfs_iam::error::{is_err_no_such_group, is_err_no_such_user}; @@ -206,11 +207,17 @@ impl Operation for DeleteGroup { ) .await?; - let group = params + let group_raw = params .get("group") .ok_or_else(|| s3_error!(InvalidArgument, "missing group name in request"))? .trim(); + // Path segments stay percent-encoded in `req.uri.path()` / matchit; IAM uses decoded names (same as GET query). + let group_decoded = percent_decode_str(group_raw) + .decode_utf8() + .map_err(|_| s3_error!(InvalidArgument, "invalid group name encoding"))?; + let group = group_decoded.trim(); + // Validate the group name format if group.is_empty() || group.len() > 256 { return Err(s3_error!(InvalidArgument, "invalid group name"));