Skip to content

Investigate reducing querystring metadata exposure of repo for query methods #39

Description

@aspiers

Background

Since #27, group-scoped query methods (app.certified.group.member.list, app.certified.group.audit.query) and the raw/body-less methods (repo.uploadBlob, group.destroy) name the target group with repo on the querystring (?repo=<handle-or-did>). This follows the AT Protocol convention (stock com.atproto.repo.* queries put repo in the querystring) and is what an unmodified @atproto/api client emits.

Concern

A querystring value commonly lands in:

  • server access logs,
  • reverse-proxy / CDN logs,
  • browser history and Referer headers.

So repo — the target group's DID — is exposed as metadata (which group's endpoint was queried) to anyone with log access. It is not a high-severity leak:

  • the auth token is in the Authorization header (not the URL),
  • the response (the member list / audit entries) is in the body (not the URL),
  • a group DID is a public, resolvable identity, not a secret.

But it is a real metadata exposure: for a group whose mere existence is sensitive, its DID appearing in shared logs is a small disclosure. See the "Querystring visibility" subsection in docs/design/aud-deprecation.md.

Why repo can't simply move to the request body

The constraint is the AT Protocol query contract, not raw HTTP. An atproto query lexicon declares a parameters block (→ querystring) and no input schema — there is no place to declare body fields for a query, and the xrpc client/server route queries as GET with params in the querystring. (HTTP GET can carry a body in the abstract, but fetch — what @atproto/api uses — forbids it, and a GET body has no defined semantics per RFC 9110.) So a stock-SDK consumer calling these typed query methods has no API to put repo in a body; the querystring is the only SDK-supported channel. Requiring a body would force callers off the typed SDK into hand-built requests — the exact DX failure #27 exists to remove.

Investigate

Given that a query body is off the table, the realistic options are:

  1. Accept repo via an HTTP header (e.g. a CGS-specific header) as an alternative to the querystring, keeping the querystring form for SDK compatibility. Does any standard atproto client set such a header on a typed query call? Likely requires bypassing the typed SDK → DX cost; investigate whether @atproto/api exposes per-call header injection cleanly.
  2. Re-type these methods as procedures (POST with a body). Non-standard for a read, and breaks "a stock query call just works" — probably a net DX loss, but worth weighing.
  3. Accept the status quo (atproto parity) and treat the metadata exposure as a known, low-severity, documented tradeoff (current state).

The bar: any mitigation must not regress the stock-@atproto/api-client DX that #27 exists to provide. If none clears that bar, close as "won't fix — atproto parity, documented."

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions