Why "encrypted in transit" isn't enough
Most "encrypted" cloud apps simply use HTTPS in transit and leave the data sitting in plaintext on the server. The provider can read it. So can a subpoena. So can an attacker who breaches the database.
For something as personal as AI memory — which often contains your codebase context, business decisions, and personal preferences — that's not good enough. Rethread's optional cloud sync uses true end-to-end encryption, where the encryption key never leaves your browser and the server only ever sees opaque ciphertext.
Default behavior: nothing leaves your device
Before we discuss the encrypted sync option, it's worth restating: by default, Rethread is local-only. All memories live in your browser's IndexedDB. Nothing is ever uploaded. Cloud sync is an explicit Pro feature you opt into.
Threat model: what we protect against
Server breach
Database, backups, R2 bucket — all leak only ciphertext.
Insider threat
Rethread employees cannot decrypt user data. There is no master key.
Subpoena / legal request
We can hand over only ciphertext. We have no decryption capability.
Network MITM
Data is already encrypted before it leaves your browser; TLS is a second layer.
Compromised device
If your computer is compromised, the attacker can read what you can read. No client-side scheme survives this.
Forgotten passphrase
By design there is no recovery. Lose the passphrase, lose the cloud copy.
The cryptographic pipeline, step by step
1. Passphrase entry
When you enable Cloud Sync, Rethread asks for a passphrase. Pick something strong — at minimum a passphrase, ideally something stored in a password manager. This passphrase never leaves your browser.
2. Salt generation
A 16-byte random salt is generated using crypto.getRandomValues. The salt is stored alongside your encrypted vault metadata so the same passphrase produces the same key on every device.
3. Key derivation: PBKDF2 → HKDF
Rethread uses two stages of key derivation, both via the browser's standard SubtleCrypto API:
- PBKDF2-SHA-256 with 200,000 iterations stretches the passphrase into a 256-bit master key. This makes brute-force attacks computationally expensive even if an attacker somehow obtained your salted ciphertext.
- HKDF-SHA-256 derives per-purpose keys from the master key — separate keys for memory encryption, conversation encryption, and metadata authentication, so a compromise of one key doesn't endanger the others.
// Conceptual outline
masterKey = PBKDF2(passphrase, salt, iterations=200_000, hash=SHA-256)
memoryKey = HKDF(masterKey, info="memory", length=256)
convoKey = HKDF(masterKey, info="conversation", length=256)
metaKey = HKDF(masterKey, info="metadata", length=256)
4. Per-record encryption
Each memory, conversation, snapshot, bucket, folder, tag, and prompt template is encrypted independently with AES-256-GCM:
- A fresh 12-byte initialization vector (IV) is generated per record using
crypto.getRandomValues. - The plaintext JSON is encrypted with
AES-256-GCM(plaintext, key, iv), producing ciphertext + a 16-byte authentication tag. - The IV + ciphertext + tag are concatenated and base64-encoded for transport.
5. Upload to Cloudflare R2
The encrypted blob is uploaded to a Cloudflare Workers + R2 backend. Each record's payload looks roughly like:
{
"record_id": "uuid-here",
"record_type":"memory",
"iv": "base64-iv...",
"ciphertext": "base64-ciphertext...",
"tag": "base64-auth-tag...",
"byte_size": 1234,
"modified_at": 1714435200,
"deleted": false
}
The server's view of your data is exactly what you see above: opaque ciphertext + minimal sync metadata. Memory contents, types, tags, bucket names, conversation text — all of it lives only inside the encrypted blob.
6. Download & decryption on a second device
When you set up Rethread on a second browser:
- Activate the same Pro license (so the server knows what records belong to you).
- Enter the same passphrase. Rethread re-derives the same master key locally using the salt fetched from the server.
- Encrypted records are streamed down and decrypted in your browser using
AES-256-GCM(ciphertext, key, iv). The auth tag is verified on every record — any tampering produces an immediate decryption failure. - Decrypted memories land in the local IndexedDB exactly as they did on the original device.
What the server actually knows about you
The Cloudflare backend sees and stores:
- Your Pro license key, used as a coarse account identifier.
- An opaque salt for key derivation (useless without the passphrase).
- Record metadata: record IDs, record types ("memory" / "conversation" / "snapshot" / etc.), soft-delete flags, last-modified timestamps, byte sizes.
- Encrypted blobs: the actual ciphertext + IV + auth tag.
- Standard request metadata (IP, user-agent) retained briefly for routing and abuse prevention.
What it does not see:
- Your passphrase, master key, or any derived keys
- The plaintext of any memory, conversation, snapshot, bucket, tag, or template
- The names of your buckets, folders, or tags
- Which AI platforms a memory came from
Forgotten passphrase: the deliberate non-feature
If you forget your passphrase, your cloud copy becomes unreadable forever. To recover, you'd need to disable sync, wipe the cloud copy, and re-enable with a new passphrase. Memories that exist only in the cloud (because all your local devices are gone) cannot be recovered.
Mitigation: store your passphrase in a password manager. Treat it like a master password.
What about the marketplace?
Rethread also ships an optional prompt template marketplace. Browsing the marketplace is anonymous (beyond standard server logs). If you choose to publish a template, that template's title, description, tags, and prompt body are shared in plaintext with the community by design — that's the whole point of publishing. Don't publish anything you wouldn't paste in a public forum.
Audit / verification path
The encryption pipeline runs entirely in browser code that ships with the extension. To verify our claims:
- Open Chrome DevTools → Network panel while sync runs. You'll see only requests to
api.rethread.dev, with bodies that are visibly opaque base64. - Open the IndexedDB inspector to see the local plaintext store — memories live in IndexedDB exactly as documented.
- Test the failure mode: enable sync on device A with passphrase X, then on device B enter passphrase Y. Decryption fails and Rethread refuses to load the cloud copy.
Encrypted memory you actually own.
Free locally. $6.99/mo or $49 lifetime for zero-knowledge cross-device sync.
Add to Chrome — Free