From bab598eb23022a61e2d74c383c4680d361a3256c Mon Sep 17 00:00:00 2001 From: quininer Date: Wed, 31 Aug 2022 12:51:31 +0800 Subject: [PATCH 1/4] Fix sensitive value leak Fix https://github.com/tower-rs/tower-http/issues/293 --- tower-http/src/sensitive_headers.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tower-http/src/sensitive_headers.rs b/tower-http/src/sensitive_headers.rs index 6dd9e6fb..bba8b5ed 100644 --- a/tower-http/src/sensitive_headers.rs +++ b/tower-http/src/sensitive_headers.rs @@ -232,9 +232,12 @@ where } fn call(&mut self, mut req: Request) -> Self::Future { + let headers = req.headers_mut(); for header in &*self.headers { - if let Some(value) = req.headers_mut().get_mut(header) { - value.set_sensitive(true); + if let http::header::Entry::Occupied(mut entry) = headers.entry(header) { + for value in entry.iter_mut() { + value.set_sensitive(true); + } } } @@ -361,9 +364,12 @@ where let this = self.project(); let mut res = ready!(this.future.poll(cx)?); + let headers = res.headers_mut(); for header in &**this.headers { - if let Some(value) = res.headers_mut().get_mut(header) { - value.set_sensitive(true); + if let http::header::Entry::Occupied(mut entry) = headers.entry(header) { + for value in entry.iter_mut() { + value.set_sensitive(true); + } } } From 333a14e4aa7f4bbb54c2d13e8a6c50b9617f2bf0 Mon Sep 17 00:00:00 2001 From: quininer Date: Wed, 31 Aug 2022 14:30:07 +0800 Subject: [PATCH 2/4] Add multiple value test for sensitive_headers --- tower-http/src/sensitive_headers.rs | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tower-http/src/sensitive_headers.rs b/tower-http/src/sensitive_headers.rs index bba8b5ed..8dbbc558 100644 --- a/tower-http/src/sensitive_headers.rs +++ b/tower-http/src/sensitive_headers.rs @@ -376,3 +376,58 @@ where Poll::Ready(Ok(res)) } } + +#[cfg(test)] +mod tests { + #[allow(unused_imports)] + use super::*; + use http::header; + use tower::{ServiceBuilder, ServiceExt}; + + #[tokio::test] + async fn multiple_value_header() { + async fn response_set_cookie(req: http::Request<()>) -> Result, ()> { + let mut iter = req.headers() + .get_all(header::COOKIE) + .iter() + .peekable(); + + assert!(iter.peek().is_some()); + + for value in iter { + assert!(value.is_sensitive()) + } + + let mut resp = http::Response::new(()); + resp.headers_mut().append(header::CONTENT_TYPE, http::HeaderValue::from_static("text/html")); + resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-1")); + resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-2")); + resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-3")); + Ok(resp) + } + + let mut service = ServiceBuilder::new() + .layer(SetSensitiveRequestHeadersLayer::new(vec![header::COOKIE])) + .layer(SetSensitiveResponseHeadersLayer::new(vec![header::SET_COOKIE])) + .service_fn(response_set_cookie); + + let mut req = http::Request::new(()); + req.headers_mut().append(header::COOKIE, http::HeaderValue::from_static("cookie+1")); + req.headers_mut().append(header::COOKIE, http::HeaderValue::from_static("cookie+2")); + + let resp = service.ready().await.unwrap().call(req).await.unwrap(); + + assert!(!resp.headers().get(header::CONTENT_TYPE).unwrap().is_sensitive()); + + let mut iter = resp.headers() + .get_all(header::SET_COOKIE) + .iter() + .peekable(); + + assert!(iter.peek().is_some()); + + for value in iter { + assert!(value.is_sensitive()) + } + } +} From b3515d8fa84954334072ed3f19a486daa26f87d3 Mon Sep 17 00:00:00 2001 From: quininer Date: Wed, 31 Aug 2022 14:57:44 +0800 Subject: [PATCH 3/4] Fix fmt --- tower-http/src/sensitive_headers.rs | 46 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/tower-http/src/sensitive_headers.rs b/tower-http/src/sensitive_headers.rs index 8dbbc558..be4b131f 100644 --- a/tower-http/src/sensitive_headers.rs +++ b/tower-http/src/sensitive_headers.rs @@ -387,10 +387,7 @@ mod tests { #[tokio::test] async fn multiple_value_header() { async fn response_set_cookie(req: http::Request<()>) -> Result, ()> { - let mut iter = req.headers() - .get_all(header::COOKIE) - .iter() - .peekable(); + let mut iter = req.headers().get_all(header::COOKIE).iter().peekable(); assert!(iter.peek().is_some()); @@ -399,30 +396,47 @@ mod tests { } let mut resp = http::Response::new(()); - resp.headers_mut().append(header::CONTENT_TYPE, http::HeaderValue::from_static("text/html")); - resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-1")); - resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-2")); - resp.headers_mut().append(header::SET_COOKIE, http::HeaderValue::from_static("cookie-3")); + resp.headers_mut().append( + header::CONTENT_TYPE, + http::HeaderValue::from_static("text/html"), + ); + resp.headers_mut().append( + header::SET_COOKIE, + http::HeaderValue::from_static("cookie-1"), + ); + resp.headers_mut().append( + header::SET_COOKIE, + http::HeaderValue::from_static("cookie-2"), + ); + resp.headers_mut().append( + header::SET_COOKIE, + http::HeaderValue::from_static("cookie-3"), + ); Ok(resp) } let mut service = ServiceBuilder::new() .layer(SetSensitiveRequestHeadersLayer::new(vec![header::COOKIE])) - .layer(SetSensitiveResponseHeadersLayer::new(vec![header::SET_COOKIE])) + .layer(SetSensitiveResponseHeadersLayer::new(vec![ + header::SET_COOKIE + ])) .service_fn(response_set_cookie); let mut req = http::Request::new(()); - req.headers_mut().append(header::COOKIE, http::HeaderValue::from_static("cookie+1")); - req.headers_mut().append(header::COOKIE, http::HeaderValue::from_static("cookie+2")); + req.headers_mut() + .append(header::COOKIE, http::HeaderValue::from_static("cookie+1")); + req.headers_mut() + .append(header::COOKIE, http::HeaderValue::from_static("cookie+2")); let resp = service.ready().await.unwrap().call(req).await.unwrap(); - assert!(!resp.headers().get(header::CONTENT_TYPE).unwrap().is_sensitive()); + assert!(!resp + .headers() + .get(header::CONTENT_TYPE) + .unwrap() + .is_sensitive()); - let mut iter = resp.headers() - .get_all(header::SET_COOKIE) - .iter() - .peekable(); + let mut iter = resp.headers().get_all(header::SET_COOKIE).iter().peekable(); assert!(iter.peek().is_some()); From 8207d3927726b47f11720a7b073bbaee3307e41f Mon Sep 17 00:00:00 2001 From: quininer Date: Wed, 31 Aug 2022 15:07:51 +0800 Subject: [PATCH 4/4] Fix fmt (take 2) --- tower-http/src/sensitive_headers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tower-http/src/sensitive_headers.rs b/tower-http/src/sensitive_headers.rs index be4b131f..3fcf18d3 100644 --- a/tower-http/src/sensitive_headers.rs +++ b/tower-http/src/sensitive_headers.rs @@ -418,7 +418,7 @@ mod tests { let mut service = ServiceBuilder::new() .layer(SetSensitiveRequestHeadersLayer::new(vec![header::COOKIE])) .layer(SetSensitiveResponseHeadersLayer::new(vec![ - header::SET_COOKIE + header::SET_COOKIE, ])) .service_fn(response_set_cookie);