atproto_core/remote
Remote-supplied URLs, parsed once at the boundary. Every hop of the OAuth
discovery chain (DID documents, protected-resource and
authorization-server metadata) hands us URLs an attacker may control, so
the kernel only ever requests an Origin or a Url from this module:
https only, no userinfo or fragment, and a host that is a public DNS
name rather than an IP literal, localhost, a single-label name, or a
local-only suffix (.local, .internal, .arpa, …).
That is the only behaviour of parse_origin and parse_url. Local
development against a devnet (http://localhost:3000) is a separate,
explicit act: parse_origin_with and parse_url_with with
AllowLocalDevelopment. An origin accepted that way remembers it
(policy_of), and the discovery code parses every URL a document names
under the policy of the origin it fetched that document from. A strict
origin therefore can never lead to a local one.
What cannot be decided at parse time is left to the transport: a public
name can still resolve to a private address (DNS rebinding), so a
server-side send must also refuse private, loopback, link-local and
unique-local destinations after resolution, must not follow redirects,
and must cap response size and request time.
Types
pub type HostRejection {
MissingHost
MalformedHost
IpLiteral
LocalName
BadPort
}
Constructors
-
MissingHost -
MalformedHost -
IpLiteral -
LocalName -
BadPort
Origin
opaqueAn origin: scheme, lowercased host, and a port. On a public host the
scheme is https and the port is omitted when it is 443; on a local host
(only under AllowLocalDevelopment) the port is always explicit. Compare
with ==; the representation is canonical.
pub opaque type Origin
Which origins a parse accepts. PublicOnly is what every function that
does not take a policy uses.
pub type Policy {
PublicOnly
AllowLocalDevelopment
}
Constructors
-
PublicOnly -
AllowLocalDevelopmentAlso accepts
httpandhttpsonlocalhost, loopback and private addresses, IP literals and local-only names, each with an explicit port. For devnets and tests only. Never enable this in production: it lets whoever controls a document redirect requests to hosts on your own network.
Url
opaqueA URL on an Origin, with a path and optional query but never userinfo or
a fragment.
pub opaque type Url
pub type UrlError {
Unparsable(url: String)
NotHttps(url: String)
HasUserinfo(url: String)
HasFragment(url: String)
NotAnOrigin(url: String)
ForbiddenHost(url: String, reason: HostRejection)
}
Constructors
-
Unparsable(url: String) -
NotHttps(url: String) -
HasUserinfo(url: String) -
HasFragment(url: String) -
NotAnOrigin(url: String)A path or query on a URL that must be a bare origin (PDS, issuer).
-
ForbiddenHost(url: String, reason: HostRejection)
Values
pub fn endpoint(origin: Origin, path: String) -> Url
A URL on origin at an absolute path, built structurally rather than by
string concatenation, so a path can never move the request to another
host.
pub fn origin_to_string(origin: Origin) -> String
pub fn parse_origin(url: String) -> Result(Origin, UrlError)
Parse a bare origin under PublicOnly. A single trailing / is accepted
and dropped; any other path, a query, or a fragment is rejected.
pub fn parse_origin_with(
url: String,
policy: Policy,
) -> Result(Origin, UrlError)
parse_origin under an explicit policy.
pub fn parse_url(url: String) -> Result(Url, UrlError)
Parse an endpoint URL (authorization, token, PAR, revocation endpoints)
under PublicOnly.
pub fn parse_url_with(
url: String,
policy: Policy,
) -> Result(Url, UrlError)
parse_url under an explicit policy.
pub fn policy_of(origin: Origin) -> Policy
The policy a parsed origin falls under: AllowLocalDevelopment when it is
http or on a non-public host (so it can only have come from a parse that
allowed it), PublicOnly otherwise. Discovery uses this to parse the URLs
a document names under the policy of the origin that served it.
pub fn request_matches_origin(
req: request.Request(body),
origin: Origin,
) -> Bool
Whether req targets exactly origin (scheme, host, and port).
pub fn to_request(url: Url) -> request.Request(String)
A bodiless GET for url. Total: the parts were validated on parse.
pub fn url_error_to_string(error: UrlError) -> String
pub fn url_to_string(url: Url) -> String