Skip to content

Commit 793a689

Browse files
authored
chore: don't redact local endpoints (#5571)
* chore: don't redact local endpoints * chore: added localhost test case
1 parent 7e872f9 commit 793a689

File tree

1 file changed

+57
-11
lines changed

1 file changed

+57
-11
lines changed

utilities/src/with_std/redact_endpoint_secret.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::net::IpAddr;
12
use regex::Regex;
23
use serde::Deserialize;
34
use std::fmt::{Debug, Display};
@@ -61,7 +62,7 @@ pub fn redact_secret_endpoint(endpoint: &str) -> String {
6162
r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
6263
let re = Regex::new(&format!("({})|({})", REGEX_ETH_SECRET, REGEX_BTC_SECRET)).unwrap();
6364
if re.is_match(endpoint) {
64-
// A 32 character hex string was found, redact it
65+
// A secret was found, redact it
6566
let mut endpoint_redacted = endpoint.to_string();
6667
// Just redact the first match so we do not get stuck in a loop if there is a mistake in the
6768
// regex
@@ -76,17 +77,24 @@ pub fn redact_secret_endpoint(endpoint: &str) -> String {
7677
}
7778
endpoint_redacted
7879
} else {
79-
// No secret was found, so just redact almost all of the url
80+
// No secret was found
8081
if let Ok(url) = Url::parse(endpoint) {
81-
format!(
82-
"{}****",
83-
endpoint
84-
.split_at(usize::min(
85-
url.scheme().len() + SCHEMA_PADDING_LEN + MAX_SECRET_CHARACTERS_REVEALED,
86-
endpoint.len()
87-
))
88-
.0
89-
)
82+
if is_local_url(&url) {
83+
// Don't redact anything if it is a local address
84+
endpoint.to_string()
85+
} else {
86+
// Redact almost all of the url
87+
format!(
88+
"{}****",
89+
endpoint
90+
.split_at(usize::min(
91+
url.scheme().len() +
92+
SCHEMA_PADDING_LEN + MAX_SECRET_CHARACTERS_REVEALED,
93+
endpoint.len()
94+
))
95+
.0
96+
)
97+
}
9098
} else {
9199
// Not a valid url, so just redact most of the string
92100
format!(
@@ -97,6 +105,18 @@ pub fn redact_secret_endpoint(endpoint: &str) -> String {
97105
}
98106
}
99107

108+
fn is_local_url(url: &Url) -> bool {
109+
match url.host_str() {
110+
Some("localhost") => true,
111+
Some(host) => match host.parse::<IpAddr>() {
112+
Ok(IpAddr::V4(ipv4)) => ipv4.is_loopback() || ipv4.is_private(),
113+
Ok(IpAddr::V6(ipv6)) => ipv6.is_loopback() || ipv6.is_unique_local(),
114+
_ => false,
115+
},
116+
None => false,
117+
}
118+
}
119+
100120
#[cfg(test)]
101121
mod tests {
102122
use super::*;
@@ -162,5 +182,31 @@ mod tests {
162182
),
163183
"btc.getblock.io/de7****/mainnet"
164184
);
185+
186+
assert_eq!(
187+
format!(
188+
"{}",
189+
SecretUrl("wss://192.168.0.123/ws/v3/d52c362116b640b98a166d08d3170a42".to_string())
190+
),
191+
"wss://192.168.0.123/ws/v3/d52****"
192+
);
193+
194+
// Local addresses without secrets should not be redacted
195+
assert_eq!(
196+
format!("{}", SecretUrl("ws://10.0.0.17".to_string())),
197+
"ws://10.0.0.17".to_string()
198+
);
199+
assert_eq!(
200+
format!("{}", SecretUrl("wss://127.0.0.1".to_string())),
201+
"wss://127.0.0.1".to_string()
202+
);
203+
assert_eq!(
204+
format!("{}", SecretUrl("https://192.168.0.123".to_string())),
205+
"https://192.168.0.123".to_string()
206+
);
207+
assert_eq!(
208+
format!("{}", SecretUrl("http://localhost".to_string())),
209+
"http://localhost".to_string()
210+
);
165211
}
166212
}

0 commit comments

Comments
 (0)