Skip to content

Enforce proxy.allowed_domains when minting signed URLs at /first-party/sign #1035

Description

@aram356

Description

Security-review follow-up (finding TS-10). Scope of this issue is strictly domain-allowlist enforcement — rate limiting, auth, and Origin checks are explicitly out of scope.

/first-party/sign (handle_first_party_proxy_sign, crates/trusted-server-core/src/proxy.rs:1644) mints signed /first-party/proxy?tsurl=…&tstoken=… URLs for any absolute http(s) URL submitted via GET ?url= or JSON POST. The only host check at mint time is the rewrite.exclude_domains denylist. The proxy.allowed_domains allowlist (crates/trusted-server-core/src/settings.rs:1567) is consulted only later, at fetch time, in proxy_with_redirects (crates/trusted-server-core/src/proxy.rs:1322; redirect hops at :1483).

Consequence: the sign endpoint acts as a signing oracle for arbitrary off-list hosts. When an allowlist is configured the minted tokens fail later at fetch time, but nothing rejects them at mint time and operators get no signal that clients are requesting signatures for hosts outside policy.

Proposed change

  • In handle_first_party_proxy_sign, validate the normalized target host against proxy.allowed_domains using the same matching semantics as the fetch path (exact match or *.suffix), and reject non-allowlisted hosts with 403 before signing.
  • Apply the check on both input forms (GET ?url= and JSON POST), including the protocol-relative (//host/...) branch, after normalization.
  • Keep existing semantics otherwise: an empty allowed_domains list continues to mean open mode (no restriction), and the rewrite.exclude_domains denylist check stays as-is.
  • Log rejections with the offending host so operators can see off-policy signing attempts.

Done when

  • /first-party/sign refuses to mint tokens for hosts not covered by a non-empty proxy.allowed_domains, on both GET and POST forms.
  • Fetch-time enforcement in proxy_with_redirects is unchanged.
  • Unit tests cover: allowlisted host, non-allowlisted host, *.suffix wildcard match, protocol-relative input, and empty-allowlist (open-mode) passthrough, for both GET and POST.
  • docs/guide/api-reference.md documents that the allowlist is enforced at mint time as well as fetch time.

Affected area

Core

Related: #414 (added the fetch-time allowlist), #982 (signing broker for opaque-origin creative iframes shares this surface).

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions