newton-core 0.4.16

newton protocol core sdk
use std::net::IpAddr;

/// Check if an IP address is in a private, reserved, or sensitive range.
///
/// Used by both the host-side WASM `HttpProvider` and the operator's Egress Service
/// to prevent SSRF attacks against internal infrastructure and AWS metadata.
pub fn is_private_ip(ip: IpAddr) -> bool {
    match ip {
        IpAddr::V4(ipv4) => {
            ipv4.is_private()
                || ipv4.is_loopback()
                || ipv4.is_link_local()
                || ipv4.is_broadcast()
                || ipv4.is_multicast()
                || ipv4.is_unspecified()
                || (ipv4.octets()[0] == 169 && ipv4.octets()[1] == 254) // AWS metadata range
        }
        IpAddr::V6(ipv6) => {
            ipv6.is_loopback()
                || ipv6.is_multicast()
                || ipv6.is_unspecified()
                || ipv6.segments()[0] & 0xfe00 == 0xfc00 // fc00::/7 unique local
                || ipv6.segments()[0] & 0xffc0 == 0xfe80 // fe80::/10 link-local
        }
    }
}

/// Check if a hostname is the AWS EC2 Instance Metadata Service.
pub fn is_aws_metadata(host: &str) -> bool {
    host == "169.254.169.254" || host == "fd00:ec2::254"
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::Ipv4Addr;

    #[test]
    fn private_ipv4_blocked() {
        assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))));
        assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))));
        assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))));
        assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
        assert!(is_private_ip(IpAddr::V4(Ipv4Addr::new(169, 254, 1, 1))));
    }

    #[test]
    fn public_ipv4_allowed() {
        assert!(!is_private_ip(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
        assert!(!is_private_ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))));
    }

    #[test]
    fn aws_metadata_blocked() {
        assert!(is_aws_metadata("169.254.169.254"));
        assert!(is_aws_metadata("fd00:ec2::254"));
        assert!(!is_aws_metadata("8.8.8.8"));
    }
}