CORTEX
All projects

VaultTabs

PROTOTYPE

Sync open browser tabs across devices. Snapshots are encrypted in the browser, but it is not zero-knowledge.

Personal project · Feb–Mar 2026 · 57 commits

THE PROBLEM

Tab-sync tools usually upload your URLs to a server in plaintext, and the built-in browser sync is tied to one vendor.

HOW IT WORKS

  • A browser extension (WXT, Chrome Manifest V3) captures open http(s) tabs, skips incognito tabs, and encrypts the list with a random AES-256-GCM master key before uploading.
  • The master key is wrapped with a key derived from the account password (PBKDF2, 100,000 iterations) and optionally with a one-time recovery code. A Next.js PWA and other extensions unwrap it locally to view snapshots and send a tab to another device.
  • A Fastify and PostgreSQL backend stores ciphertext and the wrapped keys.

THE PIPELINE

  1. ExtensionCaptures open http(s) tabs and skips incognito tabs.
  2. Encrypt in the browserRandom AES-256-GCM master key, fresh IV per snapshot.
  3. Fastify and PostgreSQLStore ciphertext and the wrapped keys.
  4. PWA or another extensionUnwraps the master key with a key derived from the password (PBKDF2) and decrypts locally.
Snapshots are encrypted in the browser, but the account password reaches the server, so this is not zero-knowledge.

ENGINEERING EVIDENCE

  • Snapshots are AES-256-GCM encrypted client-side with a fresh random 96-bit IV each, so a stolen database contains no readable tab data. A script checks this against the database. crypto.ts ↗
  • A Sep 2026 review fixed real defects: restore requests could be read or completed by any logged-in user, JWTs never expired, CORS was open outside production, and the docker-compose healthchecks were malformed so the backend never started. restore.service.ts ↗

WHAT ISN'T DONE

  • Not zero-knowledge. The account password is sent to the server (over TLS) at sign-up and login, and the same password protects the master key, so a server operator who captures passwords can decrypt every snapshot. Fixing it needs an authentication redesign, such as a separate auth secret or OPAQUE.
  • The server sees your email, device names, timestamps, snapshot sizes and restore target URLs.
  • The first README and the app copy claimed zero-knowledge. They were corrected in Sep 2026.
  • There is one integration test file. The Docker setup and the fixes above were type-checked and built but not run end to end.

NEXT STEPS

Each one comes from a gap listed above. It says what fixing the gap would take; it is not a promise.

  • Stop sending the account password to the server, by using a separate authentication secret or OPAQUE.
  • Use a stronger key-derivation function than PBKDF2 with 100,000 iterations, and encrypt restore target URLs.
  • Run the Docker setup end to end against a real database.

STACK

  • TypeScript
  • WXT
  • Next.js
  • Fastify
  • PostgreSQL
  • WebCrypto
  • Docker