NetworkSecurity

org.llm4s.core.safety.NetworkSecurity
@Stable

Network security utilities for SSRF protection.

Provides IP address validation to prevent Server-Side Request Forgery (SSRF) attacks by blocking requests to internal networks, cloud metadata endpoints, and other potentially sensitive destinations.

== Protected IP Ranges == Checked against the IANA IPv4 and IPv6 Special-Purpose Address Registries: every entry that is not globally reachable is blocked.

  • Private networks: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (RFC 1918); IPv6 unique-local fc00::/7 (RFC 4193) and the deprecated site-local fec0::/10
  • Loopback: 127.0.0.0/8, ::1
  • Unspecified / "this network": 0.0.0.0/8, ::
  • Link-local: 169.254.0.0/16, fe80::/10
  • Cloud metadata: 169.254.169.254 (AWS, GCP, Azure)
  • Multicast: 224.0.0.0/4, ff00::/8
  • Reserved 240.0.0.0/4, including the limited broadcast address 255.255.255.255
  • IETF protocol assignments 192.0.0.0/24 and the deprecated 6to4 relay anycast 192.88.99.0/24
  • Carrier-grade NAT 100.64.0.0/10, benchmarking 198.18.0.0/15 and 2001:2::/48
  • Documentation/test ranges: 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 2001:db8::/32, 3fff::/20
  • Every IPv6 address outside global unicast 2000::/3 (RFC 4291 2.4), which IANA has never allocated for routing: among others the IPv4-compatible ::/96, the SIIT IPv4-translated ::ffff:0:0:0/96, discard-only 100::/64, the dummy prefix 100:0:0:1::/64, local-use NAT64 64:ff9b:1::/48 and SRv6 5f00::/16
  • The IETF protocol assignments block 2001::/23 (Teredo 2001::/32, benchmarking, the deprecated ORCHID and the unassigned rest), except its globally reachable entries: 2001:1::1, 2001:1::2 and 2001:1::3, AMT 2001:3::/32, AS112 2001:4:112::/48, ORCHIDv2 2001:20::/28 and drone remote ID 2001:30::/28
  • An IPv6 address that embeds an IPv4 address - IPv4-mapped ::ffff:0:0/96, NAT64 64:ff9b::/96 and 6to4 2002::/16 - is blocked when the embedded IPv4 address is

The globally reachable entries of the IPv4 registry (192.31.196.0/24, 192.52.193.0/24, 192.175.48.0/24) are allowed.

== Name resolution == validateUrl and validateHostname resolve the host with InetAddress.getAllByName, which cannot be interrupted: a caller that runs them under a deadline (as the HTTP tool does) can stop waiting, but the thread doing the lookup stays blocked until the system resolver answers or gives up, by its own timeout. The address is resolved again when the connection is made, so a host whose answer changes in between (DNS rebinding) is not covered.

Attributes

Example
import org.llm4s.core.safety.NetworkSecurity
// Validate a URL before fetching
NetworkSecurity.validateUrl("https://example.com/api") // Right(())
NetworkSecurity.validateUrl("http://169.254.169.254/") // Left(NetworkError)
NetworkSecurity.validateUrl("http://192.168.1.1/admin") // Left(NetworkError)
Graph
Supertypes
class Object
trait Matchable
class Any
Self type

Members list

Value members

Concrete methods

def isBlockedHostname(hostname: String, additionalBlocked: Set[String]): Boolean

Check if a hostname should be blocked (case-insensitive).

Check if a hostname should be blocked (case-insensitive).

Value parameters

additionalBlocked

Additional hostnames to block

hostname

The hostname to check

Attributes

Returns

true if the hostname should be blocked

def isBlockedIP(ip: InetAddress): Boolean

Check if an IP address is in a private/internal range that should be blocked.

Check if an IP address is in a private/internal range that should be blocked.

Value parameters

ip

The IP address to check

Attributes

Returns

true if the IP is in a blocked range

def validateHostname(hostname: String, additionalBlockedHostnames: Set[String]): Result[Unit]

Validate a hostname for SSRF safety (without full URL parsing).

Validate a hostname for SSRF safety (without full URL parsing).

Like validateUrl, this resolves the name with InetAddress.getAllByName, which cannot be interrupted: the calling thread waits for the system resolver, whatever deadline the caller has.

Value parameters

additionalBlockedHostnames

Additional hostnames to block

hostname

The hostname to validate

Attributes

Returns

Right(()) if safe, Left(NetworkError) if blocked

def validateIP(ipString: String): Result[Unit]

Validate an IP address string directly.

Validate an IP address string directly.

Value parameters

ipString

The IP address string to validate

Attributes

Returns

Right(()) if safe, Left(NetworkError) if blocked

def validateUrl(urlString: String, additionalBlockedHostnames: Set[String], allowedProtocols: Set[String]): Result[Unit]

Validate a URL for SSRF safety.

Validate a URL for SSRF safety.

This performs DNS resolution and checks if the resolved IP is in a blocked range. It also validates the hostname against known blocked hostnames.

The lookup (InetAddress.getAllByName) cannot be interrupted, so it can block the calling thread for as long as the system resolver takes, whatever deadline the caller has; see "Name resolution" above.

Value parameters

additionalBlockedHostnames

Additional hostnames to block

allowedProtocols

Allowed URL protocols (default: http, https)

urlString

The URL to validate

Attributes

Returns

Right(()) if safe, Left(NetworkError) if blocked

Concrete fields

val CloudMetadataIP: String

Cloud metadata IP address (used by AWS, GCP, Azure).

Cloud metadata IP address (used by AWS, GCP, Azure).

Attributes

val DefaultBlockedHostnames: Set[String]

Default blocked hostnames (in addition to IP-based blocking).

Default blocked hostnames (in addition to IP-based blocking).

Attributes