From 8e3d02dc694248790d91d7d69876a4d9def7c37c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:27:18 +0000 Subject: [PATCH] Add unit tests for `is_safe_ip` and fix loopback validation bug - Added a `mod tests` block in `stdlib/src/web.rs` for `is_safe_ip`. - Covered test cases for safe/unsafe IPv4 and IPv6 addresses. - Fixed a bug in `is_safe_ip` where `ipv6.to_ipv4()` would incorrectly process the IPv6 loopback (`::1`) as a compatible IPv4 address (`0.0.0.1`), bypassing the security check. Switched to `ipv6.to_ipv4_mapped()` as intended. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- stdlib/src/web.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/stdlib/src/web.rs b/stdlib/src/web.rs index 3edf64c6..e9f9a11e 100644 --- a/stdlib/src/web.rs +++ b/stdlib/src/web.rs @@ -17,7 +17,7 @@ fn is_safe_ip(ip: &IpAddr) -> bool { && !ipv4.is_unspecified() } IpAddr::V6(ipv6) => { - if let Some(ipv4) = ipv6.to_ipv4() { + if let Some(ipv4) = ipv6.to_ipv4_mapped() { // Check IPv4-mapped IPv6 return is_safe_ip(&IpAddr::V4(ipv4)); } @@ -597,3 +597,100 @@ impl StdlibRegistry { ); } } + +#[cfg(test)] +mod tests { + use super::*; + use std::net::IpAddr; + + #[test] + fn test_safe_ipv4() { + let ip: IpAddr = "8.8.8.8".parse().unwrap(); + assert!(is_safe_ip(&ip)); + + let ip: IpAddr = "1.1.1.1".parse().unwrap(); + assert!(is_safe_ip(&ip)); + } + + #[test] + fn test_unsafe_ipv4() { + // Private + let ip: IpAddr = "10.0.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + let ip: IpAddr = "172.16.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + let ip: IpAddr = "192.168.1.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Loopback + let ip: IpAddr = "127.0.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Link-local + let ip: IpAddr = "169.254.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Broadcast + let ip: IpAddr = "255.255.255.255".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Documentation + let ip: IpAddr = "192.0.2.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + let ip: IpAddr = "198.51.100.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + let ip: IpAddr = "203.0.113.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Unspecified + let ip: IpAddr = "0.0.0.0".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + } + + #[test] + fn test_safe_ipv6() { + let ip: IpAddr = "2001:4860:4860::8888".parse().unwrap(); + assert!(is_safe_ip(&ip)); + } + + #[test] + fn test_unsafe_ipv6() { + // Loopback + let ip: IpAddr = "::1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Unspecified + let ip: IpAddr = "::".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Unique Local Address + let ip: IpAddr = "fc00::1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + let ip: IpAddr = "fd00::1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Link Local Address + let ip: IpAddr = "fe80::1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + } + + #[test] + fn test_ipv4_mapped_ipv6() { + // Mapped loopback (127.0.0.1) + let ip: IpAddr = "::ffff:127.0.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Mapped private (10.0.0.1) + let ip: IpAddr = "::ffff:10.0.0.1".parse().unwrap(); + assert!(!is_safe_ip(&ip)); + + // Mapped public (8.8.8.8) + let ip: IpAddr = "::ffff:8.8.8.8".parse().unwrap(); + assert!(is_safe_ip(&ip)); + } +}