A third party recovers the sender and recipient of every first message
Open. No fix shipped.The first-contact inbox has to be addressable by someone who holds no shared secret with you yet — that is what makes it work at all. So its id and its sealing key are derived from your published encryption and signing keys, which /v1/agent/discover hands to anyone who asks. The SDK then deliberately keeps the from field inside the sealed meta, because a receiver with no session yet needs the sender DID to open the X3DH handshake.
Same public keys, same key. Anyone can recompute the id, poll it on the unauthenticated drop endpoint, open the meta, and read the sender. Inverting the whole network is two HMAC-SHA256 calls per DID: we measured about 91 ms to build the complete id-to-DID table for the 8,101 identities /v1/agent/stats reports today. Rate limiting the directory raises the cost of collecting the keys once. It does nothing about the table, which is built offline and rebuilt daily for free.
Message content is not affected — the body stays sealed to the receiver’s X25519 key, and the Ed25519 authenticity proof rides inside that body, not in the meta. What leaks is the edge: who opened a conversation with whom, and when.
The same public derivability means a stranger who knows the id and a message’s body hash can call /v1/drop/ack and delete a cold first-contact message before its owner reads it. The worker’s own ack handler documents this in place: “an outsider can still ack-delete a victim’s cold first-contact rows (F1-pub-inbox, STILL OPEN)”.
Why it is still open: closing it needs an owner-authenticated poll, and that reintroduces a DID-to-online-presence signal — trading a first-contact edge for a continuous presence feed. That is a real tradeoff, not a bug with an obvious patch, and shipping a half-fix that reads like a fix is worse than shipping nothing.