From db5dc93608c629cd5ff9227c5814a4d02579077d Mon Sep 17 00:00:00 2001 From: danbugs Date: Sun, 17 May 2026 06:39:04 +0000 Subject: [PATCH] fix: block loopback addresses by default in NetworkPolicy Signed-off-by: danbugs --- host/src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/host/src/lib.rs b/host/src/lib.rs index 2e4dac4..461f8d0 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -399,6 +399,16 @@ impl NetworkPolicy { )); } + // Block loopback addresses (127.0.0.0/8, ::1) for all policy + // variants. Host-local services typically trust loopback traffic + // and perform no authentication. + if addr.ip().is_loopback() { + return Err(anyhow!( + "network policy denies connection to loopback address {}", + addr + )); + } + match self { NetworkPolicy::AllowAll => Ok(()), NetworkPolicy::AllowList(al) => { @@ -2922,6 +2932,36 @@ mod tests { ); } + #[test] + fn net_loopback_blocked() { + use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; + + let policy = NetworkPolicy::AllowAll; + let lo4 = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 80); + assert!( + policy.check(&lo4).is_err(), + "AllowAll must block IPv4 loopback" + ); + + let lo6 = SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 80); + assert!( + policy.check(&lo6).is_err(), + "AllowAll must block IPv6 loopback" + ); + + // BlockList should also block loopback + let bl = BlockList::from_hosts(&["192.0.2.1"]).unwrap(); + let policy = NetworkPolicy::BlockList(bl); + assert!( + policy.check(&lo4).is_err(), + "BlockList must block IPv4 loopback" + ); + assert!( + policy.check(&lo6).is_err(), + "BlockList must block IPv6 loopback" + ); + } + #[test] fn net_tools_registered_with_blocklist() { let mut tools = ToolRegistry::new();