pub struct SafeUrl(/* private fields */);Expand description
A validated URL that rejects dangerous schemes and URLs resolving to network ranges that enable server-side request forgery.
§Allowed schemes
Only http and https. Rejects file://, gopher://, javascript:,
data:, and any other non-http(s) scheme.
§Blocked host ranges (SSRF prevention)
Every URL whose host string parses as one of the following IP families
is rejected with BoundaryRejection::SsrfAttempt:
| CIDR | What it is | Why it’s blocked |
|---|---|---|
10.0.0.0/8 | RFC 1918 private | Classic LAN SSRF |
172.16.0.0/12 | RFC 1918 private | Classic LAN SSRF |
192.168.0.0/16 | RFC 1918 private | Classic LAN SSRF |
169.254.0.0/16 | IPv4 link-local | AWS IMDS (169.254.169.254) — credential exfiltration |
127.0.0.0/8 | IPv4 loopback | Bypass to localhost services |
224.0.0.0/4 | IPv4 multicast | Lateral-movement response surface |
0.0.0.0/32 | IPv4 unspecified | Stack-internal vulnerabilities |
fc00::/7 | IPv6 Unique Local Address | Analogue of RFC 1918 on IPv6 |
fe80::/10 | IPv6 link-local | IPv6 analogue of IMDS attack vector |
::1/128 | IPv6 loopback | Bypass to localhost services on IPv6 |
ff00::/8 | IPv6 multicast | Same as IPv4 multicast, on IPv6 |
::/128 | IPv6 unspecified | Stack-internal vulnerabilities |
The blocked set is variant-analysis-tested — each CIDR has a named
regression test in sg_gate_a_safeurl_cidrs.rs, so removing a single
line from the internal classifier fails a specific, named test.
DNS rebinding is not prevented by SafeUrl alone; validate only
accepts a host string. If you resolve and connect, perform a fresh
is_private_ip check on the resolved address, or pin to a specific
resolver policy.
§Examples
use secure_boundary::safe_types::SafeUrl;
// Public URL — accepted.
let url = SafeUrl::try_from("https://example.com/api").unwrap();
assert_eq!(url.as_inner(), "https://example.com/api");
// Loopback — rejected.
assert!(SafeUrl::try_from("http://127.0.0.1/admin").is_err());
// AWS IMDS — rejected.
assert!(SafeUrl::try_from("http://169.254.169.254/latest/meta-data").is_err());
// IPv6 link-local — rejected.
assert!(SafeUrl::try_from("http://[fe80::1]/").is_err());
// Dangerous scheme — rejected.
assert!(SafeUrl::try_from("javascript:alert(1)").is_err());