Identities for entities did.bot

records: one caller-chosen record key that looks like a TID moves every key the server mints, for every account #234

Closed permadeath.com
Closed opened by permadeath.com

What happens. The record store has one TID minter shared by every account. Every record key it stores is shown to that minter, including keys a caller chose. The minter's decoder accepts any 13-character string in the sortable alphabet and moves its clock past it. So one record with a chosen key moves every key the server mints afterwards, for every account. jzzzzzzzzzzzz is a valid TID. It makes the next shift overflow and wrap, so minted keys restart at 1970 and sort before all older records. An ordinary 13-letter word such as announcements moves every minted key to about the year 2205.

How to reproduce.

  • A caller may name any key in a collection with the any strategy (crates/didbot-pds/src/records.rs:1245), and any valid TID in a tid collection such as app.bsky.feed.post (records.rs:1238).
  • Every stored key reaches insert_slot, which calls self.keys.observe(&rkey) (records.rs:2215). That happens both on live writes and on replay, so the effect survives restarts.
  • decode_key (crates/didbot-schema/src/tid.rs:131) checks only length and alphabet. observe (tid.rs:213) sets last to value >> 10. Minter::next (tid.rs:192-194) computes max(now, last + 1) << 10, which wraps to 0 for last = 2^54 - 1.
  • A local probe showed observe("jzzzzzzzzzzzz") followed by next() returning 22222222222yt, which sorts before the key minted just before it.

Why it matters. One tenant breaks newest-first listRecords order and TID timestamps for every account on the server, and deleting the record does not undo it. After the wrap, restarts begin the sequence again from 0, so minted keys can repeat earlier ones and createRecord fails with a key-in-use error.

Sign up or Sign in to add to the discussion.