Skip to content

Commit 263ad73

Browse files
authored
Sanitize error message for sensitive requests (apache#6074)
* Sanitize error message for sensitive requests * Clippy
1 parent 9c4c95f commit 263ad73

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

src/aws/credential.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ async fn web_identity(
610610
])
611611
.retryable(retry_config)
612612
.idempotent(true)
613+
.sensitive(true)
613614
.send()
614615
.await?
615616
.bytes()

src/client/retry.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ pub struct RetryableRequest {
174174
retry_timeout: Duration,
175175
backoff: Backoff,
176176

177+
sensitive: bool,
177178
idempotent: Option<bool>,
178179
payload: Option<PutPayload>,
179180
}
@@ -190,6 +191,14 @@ impl RetryableRequest {
190191
}
191192
}
192193

194+
/// Set whether this request contains sensitive data
195+
///
196+
/// This will avoid printing out the URL in error messages
197+
#[allow(unused)]
198+
pub fn sensitive(self, sensitive: bool) -> Self {
199+
Self { sensitive, ..self }
200+
}
201+
193202
/// Provide a [`PutPayload`]
194203
pub fn payload(self, payload: Option<PutPayload>) -> Self {
195204
Self { payload, ..self }
@@ -206,6 +215,11 @@ impl RetryableRequest {
206215
.idempotent
207216
.unwrap_or_else(|| self.request.method().is_safe());
208217

218+
let sanitize_err = move |e: reqwest::Error| match self.sensitive {
219+
true => e.without_url(),
220+
false => e,
221+
};
222+
209223
loop {
210224
let mut request = self
211225
.request
@@ -238,6 +252,7 @@ impl RetryableRequest {
238252
};
239253
}
240254
Err(e) => {
255+
let e = sanitize_err(e);
241256
let status = r.status();
242257
if retries == max_retries
243258
|| now.elapsed() > retry_timeout
@@ -280,6 +295,8 @@ impl RetryableRequest {
280295
}
281296
},
282297
Err(e) => {
298+
let e = sanitize_err(e);
299+
283300
let mut do_retry = false;
284301
if e.is_connect()
285302
|| e.is_body()
@@ -365,6 +382,7 @@ impl RetryExt for reqwest::RequestBuilder {
365382
backoff: Backoff::new(&config.backoff),
366383
idempotent: None,
367384
payload: None,
385+
sensitive: false,
368386
}
369387
}
370388

@@ -565,6 +583,48 @@ mod tests {
565583
"{e}"
566584
);
567585

586+
let url = format!("{}/SENSITIVE", mock.url());
587+
for _ in 0..=retry.max_retries {
588+
mock.push(
589+
Response::builder()
590+
.status(StatusCode::BAD_GATEWAY)
591+
.body("ignored".to_string())
592+
.unwrap(),
593+
);
594+
}
595+
let res = client.request(Method::GET, url).send_retry(&retry).await;
596+
let err = res.unwrap_err().to_string();
597+
assert!(err.contains("SENSITIVE"), "{err}");
598+
599+
let url = format!("{}/SENSITIVE", mock.url());
600+
for _ in 0..=retry.max_retries {
601+
mock.push(
602+
Response::builder()
603+
.status(StatusCode::BAD_GATEWAY)
604+
.body("ignored".to_string())
605+
.unwrap(),
606+
);
607+
}
608+
609+
// Sensitive requests should strip URL from error
610+
let req = client
611+
.request(Method::GET, &url)
612+
.retryable(&retry)
613+
.sensitive(true);
614+
let err = req.send().await.unwrap_err().to_string();
615+
assert!(!err.contains("SENSITIVE"), "{err}");
616+
617+
for _ in 0..=retry.max_retries {
618+
mock.push_fn(|_| panic!());
619+
}
620+
621+
let req = client
622+
.request(Method::GET, &url)
623+
.retryable(&retry)
624+
.sensitive(true);
625+
let err = req.send().await.unwrap_err().to_string();
626+
assert!(!err.contains("SENSITIVE"), "{err}");
627+
568628
// Shutdown
569629
mock.shutdown().await
570630
}

0 commit comments

Comments
 (0)