Space-only blobs are readable through the public `com.atproto.sync.getBlob`
Describe the bug
A blob referenced only by a record in a space is served by com.atproto.sync.getBlob to an unauthenticated client that knows the blob's CID.
To Reproduce
Create a space with an empty member list, upload a blob, and reference it from one record inside that space. Then, with no credential on either call:
com.atproto.space.getBlob -> HTTP 401
com.atproto.sync.getBlob -> HTTP 200 "members only"Script:
PDS=http://localhost:2583
TOK=$(curl -sS "$PDS/xrpc/com.atproto.server.createSession" -H 'content-type: application/json' \
-d '{"identifier":"alice.test","password":"alice-pass"}' | jq -r .accessJwt)
DID=$(curl -sS "$PDS/xrpc/com.atproto.server.getSession" -H "authorization: Bearer $TOK" | jq -r .did)
SPACE=$(curl -sS "$PDS/xrpc/com.atproto.simplespace.createSpace" -H "authorization: Bearer $TOK" \
-H 'content-type: application/json' -d "{\"type\":\"my.repro.private\",\"skey\":\"leak-$(date +%s%N)\",
\"policy\":{\"\$type\":\"com.atproto.simplespace.defs#memberListPolicy\"},
\"appAccess\":{\"\$type\":\"com.atproto.simplespace.defs#open\"}}" | jq -r .uri)
CID=$(curl -sS "$PDS/xrpc/com.atproto.repo.uploadBlob" -H "authorization: Bearer $TOK" \
-H 'content-type: text/plain' --data-binary 'members only' | jq -r '.blob.ref["$link"]')
curl -sS -o /dev/null "$PDS/xrpc/com.atproto.space.createRecord" -H "authorization: Bearer $TOK" \
-H 'content-type: application/json' -d "{\"space\":\"$SPACE\",\"repo\":\"$DID\",
\"collection\":\"my.repro.doc\",\"rkey\":\"secret\",\"validate\":false,
\"record\":{\"\$type\":\"my.repro.doc\",\"file\":{\"\$type\":\"blob\",
\"ref\":{\"\$link\":\"$CID\"},\"mimeType\":\"text/plain\",\"size\":12}}}"
# no credential on either call
curl -s -o /dev/null -w 'space.getBlob -> %{http_code}\n' \
"$PDS/xrpc/com.atproto.space.getBlob?space=$SPACE&repo=$DID&cid=$CID"
curl -s -w '\nsync.getBlob -> %{http_code}\n' \
"$PDS/xrpc/com.atproto.sync.getBlob?did=$DID&cid=$CID"Expected behavior
The Permissioned Data proposal's "Blob sync" section specifies blobs are "fetched via com.atproto.space.getBlob with the relevant space credential".
I would expect the space credential to be required via any access method that returns space-only content.
Since com.atproto.sync.getBlob is public, refusing to act on space-only blobs is probably the desirable behavior rather than requiring a space credential.
Details
- Spaces alpha local testing
- Branch
permissioned-data@89deb9f, against the@atproto/dev-envmulti-PDS network.
Source: bluesky-social/atproto