From 2e6f6768bc85e24f6d6b97572dcb5a6e56c500d8 Mon Sep 17 00:00:00 2001 From: LORDBABUINO Date: Tue, 26 May 2026 14:06:46 -0300 Subject: [PATCH] fix(api): reject empty descriptors/utxos arrays with bad_request --- api/src/routes/wallet.rs | 44 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/api/src/routes/wallet.rs b/api/src/routes/wallet.rs index 0a6a6a9..2239a0b 100644 --- a/api/src/routes/wallet.rs +++ b/api/src/routes/wallet.rs @@ -41,8 +41,10 @@ impl ScanRequestBody { fn into_scan_target(self) -> Result { match (self.descriptor, self.descriptors, self.utxos) { (Some(d), None, None) => Ok(ScanTarget::Descriptor(d)), - (None, Some(ds), None) => Ok(ScanTarget::Descriptors(ds)), - (None, None, Some(utxos)) => Ok(ScanTarget::Utxos(utxos)), + (None, Some(ds), None) if !ds.is_empty() => Ok(ScanTarget::Descriptors(ds)), + (None, Some(_), None) => Err(ApiError::bad_request("`descriptors` must not be empty")), + (None, None, Some(utxos)) if !utxos.is_empty() => Ok(ScanTarget::Utxos(utxos)), + (None, None, Some(_)) => Err(ApiError::bad_request("`utxos` must not be empty")), (None, None, None) => Err(ApiError::bad_request( "one input source is required: descriptor, descriptors, or utxos", )), @@ -127,6 +129,44 @@ mod tests { assert_eq!(body["error"]["code"], "bad_request"); } + #[tokio::test] + async fn post_scan_rejects_empty_descriptors_list() { + let response = app() + .oneshot( + Request::builder() + .uri("/api/wallet/scan") + .method("POST") + .header("content-type", "application/json") + .body(Body::from(json!({ "descriptors": [] }).to_string())) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + let body = read_json(response).await; + assert_eq!(body["error"]["code"], "bad_request"); + } + + #[tokio::test] + async fn post_scan_rejects_empty_utxos_list() { + let response = app() + .oneshot( + Request::builder() + .uri("/api/wallet/scan") + .method("POST") + .header("content-type", "application/json") + .body(Body::from(json!({ "utxos": [] }).to_string())) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + let body = read_json(response).await; + assert_eq!(body["error"]["code"], "bad_request"); + } + #[tokio::test] async fn post_scan_returns_503_without_rpc_config() { let response = app()