Cabinet accessible without encryption identity

did:plc:wydyrngmxbcsqdvhmd7whmye opened this Mar 20, 2026 0 comments
did:plc:wydyrngmxbcsqdvhmd7whmye opened Mar 20, 2026

Summary

The /cabinet route guard checks session.status but not identity.status. A user who logs in but does not complete seed phrase setup can navigate directly to /cabinet/files. Crypto operations then run with missing keys, producing errors or potentially writing unrecoverable ciphertext.

Reproduction

  1. Log in via OAuth (session becomes active)
  2. Do NOT complete seed phrase setup (identity stays unchecked or fresh)
  3. Navigate directly to /cabinet/files via URL bar or deep link
  4. The route loads — loadCabinet fires, calls storage.loadIdentity(did) which throws
  5. Cabinet shows a blank/error state instead of redirecting to /devices

Impact

  • Silent encryption failures if identity happens to be partially available
  • Confusing UX — user sees a broken cabinet instead of being guided to set up their keys
  • Deep links to cabinet files bypass the normal devices → identity setup → cabinet flow

Location

web/src/routes/cabinet/route.tsx:65-78 — the beforeLoad guard:

beforeLoad: async () => {
  const state = useAuthStore.getState();
  if (state.session.status === "initializing") {
    await state.boot();
  }
  if (useAuthStore.getState().session.status !== "active") {
    throw redirect({ to: "/devices/login" });
  }
  // No identity check here — the bug
},

Proposed fix

Check for local identity in IndexedDB before allowing cabinet access:

const { did } = useAuthStore.getState().session;
const hasIdentity = await storage.loadIdentity(did).then(() => true, () => false);
if (!hasIdentity) {
  throw redirect({ to: "/devices" });
}

Important: do NOT call checkIdentity() in the route guard — it does a PDS call (fetchUpstreamPublicKey) that blocks rendering while WASM initializes. Check IndexedDB directly instead.

Regression test

e2e-tests/tests/web/identity-guard.test.ts — logs in, skips seed phrase, navigates to /cabinet, verifies the page is blocked.

No activity yet.

cospan · schematic version control on atproto built on AT Protocol