#[non_exhaustive]pub struct OAuthSsrfAllowlist {
pub hosts: Vec<String>,
pub cidrs: Vec<String>,
}Expand description
Operator-trusted SSRF allowlist for OAuth/JWKS targets that resolve to addresses normally blocked by the post-DNS SSRF guard.
Default: empty. With both fields empty (or this struct unset), the existing fail-closed behavior is unchanged: any OAuth/JWKS URL resolving to RFC 1918, loopback, link-local, CGNAT, multicast, broadcast, unspecified, IPv6 unique-local / link-local / multicast, documentation, benchmarking, or reserved ranges is rejected before connect.
Cloud-metadata addresses remain unbypassable – operators cannot opt in to metadata-service exposure. This carve-out covers:
- IPv4
169.254.169.254(AWS / GCP / Azure). - IPv4
100.100.100.200(Alibaba Cloud / Tencent Cloud). - IPv6
fd00:ec2::254(AWS IMDSv2 over IPv6). - IPv6
fd20:ce::254(GCP).
See SECURITY.md § “Operator allowlist”.
Both lists are evaluated additively: a target is allowed if its
hostname is in hosts or every resolved IP for
the target falls within at least one CIDR in cidrs.
The allowlist applies to all six configured OAuth URL fields
(OAuthConfig::issuer, OAuthConfig::jwks_uri,
OAuthProxyConfig::authorize_url, OAuthProxyConfig::token_url,
OAuthProxyConfig::introspection_url,
OAuthProxyConfig::revocation_url,
TokenExchangeConfig::token_url) and to the per-redirect-hop
SSRF guard when a redirect target is a literal IP in a configured
CIDR.
Entries are validated at startup: literal IPs in hosts, non-zero
host bits in cidrs, malformed CIDRs, and entries containing
ports / userinfo / paths are all rejected by
OAuthConfig::validate.
§Example
use rmcp_server_kit::oauth::{OAuthConfig, OAuthSsrfAllowlist};
let mut allowlist = OAuthSsrfAllowlist::default();
allowlist.hosts.push("rhbk.ops.example.com".into());
allowlist.cidrs.push("10.0.0.0/8".into());
let cfg = OAuthConfig::builder(
"https://rhbk.ops.example.com/realms/ops",
"mcp",
"https://rhbk.ops.example.com/realms/ops/protocol/openid-connect/certs",
)
.ssrf_allowlist(allowlist)
.build();
cfg.validate().expect("operator allowlist parses");Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.hosts: Vec<String>Hostnames allowed to resolve into otherwise-blocked address ranges. Exact match, case-insensitive, no wildcards. Each entry must be a bare DNS hostname: no scheme, no port, no userinfo, not a literal IP.
cidrs: Vec<String>CIDR blocks whose addresses are considered trusted even when
the address would otherwise be blocked. Accepts both IPv4
(e.g. 10.0.0.0/8) and IPv6 (e.g. fd00::/8).
Cloud-metadata addresses inside any listed range remain blocked.
Trait Implementations§
Source§impl Clone for OAuthSsrfAllowlist
impl Clone for OAuthSsrfAllowlist
Source§fn clone(&self) -> OAuthSsrfAllowlist
fn clone(&self) -> OAuthSsrfAllowlist
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more