fraiseql_core/http/client.rs
1//! SSRF-safe HTTP client construction.
2//!
3//! All outbound HTTP clients that contact external services (OIDC JWKS endpoints,
4//! Vault, federation subgraphs, webhooks) must be built with this module to ensure
5//! a consistent security baseline.
6
7use std::time::Duration;
8
9use reqwest::{Client, ClientBuilder, redirect};
10
11/// Build an HTTP client that is safe for SSRF-sensitive outbound requests.
12///
13/// # Policy
14///
15/// - **Redirects disabled**: a redirect response (`3xx`) is treated as an error, preventing
16/// redirect-chain attacks that bypass URL-validation guards applied to the initial URL (e.g. a
17/// subgraph redirecting to `169.254.169.254`).
18/// - **HTTPS only**: plain HTTP connections are rejected, preventing protocol-downgrade via
19/// redirect.
20/// - **Caller-supplied timeout**: applied to all requests; prevents slow-loris hangs on malicious
21/// or misconfigured endpoints.
22///
23/// # Errors
24///
25/// Returns a [`reqwest::Error`] if TLS initialisation fails (extremely rare;
26/// indicates a platform TLS misconfiguration).
27pub fn build_ssrf_safe_client(timeout: Duration) -> reqwest::Result<Client> {
28 ClientBuilder::new()
29 .redirect(redirect::Policy::none())
30 .https_only(true)
31 .timeout(timeout)
32 .build()
33}