Class UriSafetyValidator
- Namespace
- NetPdf
- Assembly
- NetPdf.dll
Per Phase B B-7 — the SSRF / SSRP gate every resource-loader implementation is expected to call before issuing an outbound fetch. Combines two checks:
- Scheme allowlist — only schemes enabled on the
active SecurityPolicy are accepted. Default policy
(SafeDefault) accepts
file:only when the path is under BaseUri +data:inline content; bothhttp:andhttps:are off. - Private / loopback / link-local IP blocklist for
HTTP(S) hosts. Catches the standard SSRF amplifier set: cloud-metadata
endpoints (
169.254.169.254AWS / GCE / Azure / Alibaba;fd00::/8IPv6 ULA), localhost (127.0.0.0/8,::1), private LAN (10/8,172.16/12,192.168/16,fc00::/7), link-local (169.254/16,fe80::/10), multicast (224.0.0.0/4,ff00::/8), and unspecified (0.0.0.0,::). Hosts that resolve via DNS are NOT validated here — the loader must resolve to IP, then re-validate to defend against DNS rebinding. IsBlockedIp(IPAddress, out string) exposes the IP check standalone for that use.
Phase B contract. NetPdf v1 ships with no default loader, so this
validator's only client today is unit tests. Phase 5 wires a real
IResourceLoader implementation that calls
ValidateScheme(Uri, SecurityPolicy) at intent time + IsBlockedIp(IPAddress, out string)
after DNS resolution, refusing the fetch on any "unsafe" verdict and
emitting RES-LOAD-FAILED-001 with the rejection reason.
What this does NOT do. Network policy (firewalls, egress proxies, captive portals) belongs at the OS / fabric layer; this validator addresses application-level SSRF defense only. It also does not handle HTTP redirects — the loader must re-validate the redirect target host after each hop.
public static class UriSafetyValidator
- Inheritance
-
UriSafetyValidator
- Inherited Members
Methods
IsBlockedIp(IPAddress, out string)
True when ip falls in any of the
well-known SSRF amplifier ranges (loopback, private, link-local,
cloud-metadata, multicast, unspecified). The reason
out parameter names the matching range so the caller can produce a
specific diagnostic.
public static bool IsBlockedIp(IPAddress ip, out string reason)
Parameters
Returns
Validate(Uri, SecurityPolicy)
Validate uri's scheme + host against
policy. For host validation, the URI host is parsed
as an IP literal where applicable; symbolic hostnames pass the host
check (the loader is expected to call IsBlockedIp(IPAddress, out string) after
DNS resolution to defend against DNS rebinding).
public static UriSafetyValidator.Verdict Validate(Uri uri, SecurityPolicy policy)
Parameters
uriUripolicySecurityPolicy
Returns
ValidateRedirect(Uri, Uri, SecurityPolicy, int)
Per Phase C C-6 — validate an HTTP redirect target. The
loader calls this for every Location: header before issuing
the next-hop fetch. Three checks layered on top of
Validate(Uri, SecurityPolicy):
<ol><li>The redirect target itself passes scheme + host
policy (delegates to <xref href="NetPdf.UriSafetyValidator.Validate(System.Uri%2cNetPdf.SecurityPolicy)" data-throw-if-not-resolved="false"></xref>) — re-checks the IP
blocklist on the new host so an open-redirect → SSRF chain
(initial URL safe, redirect target on <code>169.254.169.254</code>) is
blocked at the moment of redirection.</li><li>The hop count is below
<xref href="NetPdf.SecurityPolicy.MaxRedirectHops" data-throw-if-not-resolved="false"></xref>. Each call records
one hop; once exhausted, return <xref href="NetPdf.UriSafetyValidator.SafetyOutcome.Unsafe" data-throw-if-not-resolved="false"></xref>
with a redirect-chain reason.</li><li>Cross-scheme downgrade rejection: <code>https</code>
→ <code>http</code> redirects are blocked (typical browser behavior +
defense against MITM-induced downgrade). Same-scheme +
<code>http</code> → <code>https</code> upgrades pass.</li></ol>
public static UriSafetyValidator.Verdict ValidateRedirect(Uri origin, Uri redirectTarget, SecurityPolicy policy, int hopsAlreadyFollowed)
Parameters
originUriredirectTargetUripolicySecurityPolicyhopsAlreadyFollowedint
Returns
ValidateScheme(Uri, SecurityPolicy)
Scheme-only check (no host inspection). Useful when the caller has not yet resolved the URL or wants to short-circuit on scheme rejection before paying DNS cost.
public static UriSafetyValidator.Verdict ValidateScheme(Uri uri, SecurityPolicy policy)
Parameters
uriUripolicySecurityPolicy