Skip to main content

guarded_post_json

Function guarded_post_json 

Source
pub async fn guarded_post_json(
    client: &Client,
    url: &str,
    extra_headers: &[(HeaderName, HeaderValue)],
    body: Vec<u8>,
) -> Result<Response>
Expand description

POST a JSON body to a user-influenced URL through the SSRF guard.

The write-side counterpart to guarded_get_no_privacy, and the only way crate::atproto::PdsClient is allowed to reach a PDS host it did not choose. It runs the same scheme allow-list, the same IP allow-list, and the same connect-pinning (via pinned_client), so the DNS-rebinding window between “assert_public_target said this host is public” and “the TCP handshake happens” is closed for writes exactly as it is for reads.

Content-Type: application/json is set here rather than by the caller, so the one header the XRPC wire format requires cannot be forgotten; the caller passes only its credential header(s).

Redirects are refused, not followed — the single deliberate divergence from guarded_get. A 307/308 re-sends the method and the body verbatim, and reqwest’s cross-origin header sanitisation only strips headers: an app password or a record body lives in the JSON payload, so a hostile PDS answering 307 Location: https://evil.example/collect would exfiltrate it however carefully the headers were handled. There is no legitimate reason for a PDS to redirect an com.atproto.repo.* write, so the safe behaviour and the correct behaviour coincide: Err, loudly.