An export or encrypted backup can silently miss secrets. When a secret fails to decrypt in the browser, it is dropped from the file and the user is not told. A user who relies on that backup finds out only when restoring.
Where, at development b5727e0:
src/views/SecretList.vue:1223-1238 decryptAllSecrets() decrypts each secret in a try, and the empty catch at :1233-1236 skips any that fail.
src/views/SecretList.vue:1247-1250 openExport() hands only the decrypted list to the export dialog. No count of skipped secrets travels with it.
src/views/SecretList.vue:1259-1262 openCxp() does the same for the CXP transfer.
|
*/ |
|
async decryptAllSecrets() { |
|
const store = this.secretStore |
|
// Pull the WHOLE vault (the export covers everything, not just the |
|
// paginated view); paged within the server's per-request cap. |
|
await store.fetchAllSecrets() |
|
const out = [] |
|
for (const secret of store.secrets) { |
|
try { |
|
out.push(await store.decryptSecret(secret)) |
|
} catch { |
|
// A secret whose suite is blocked/revoked cannot be decrypted; |
|
// skip it rather than failing the whole export. |
|
} |
|
} |
|
return out |
|
}, |
|
|
|
/** |
|
* Open the export dialog after decrypting the vault client-side. |
|
* |
|
* @return {Promise<void>} |
|
* @spec openspec/changes/secret-export-gdpr/specs/secret-export/spec.md |
|
*/ |
|
async openExport() { |
|
this.decryptedSecrets = await this.decryptAllSecrets() |
|
this.exportOpen = true |
|
}, |
The comment names a blocked or revoked suite as the reason. That is exactly the case where a user most needs to know what the file does not hold.
Specified fix: openspec/changes/portability-export-choice-and-restore-fidelity, design D5 and task 1.3 (the dialog shows how many secrets were left out and lets the user cancel).
Found by the OpenSpec pass on 27 Sep 2026 and re-read at b5727e0 on 28 Sep.
Live check: make one secret undecryptable (for example, encrypted to a suite that is now revoked), export the vault, and compare the number of secrets in the file with the number in the list.
An export or encrypted backup can silently miss secrets. When a secret fails to decrypt in the browser, it is dropped from the file and the user is not told. A user who relies on that backup finds out only when restoring.
Where, at development b5727e0:
src/views/SecretList.vue:1223-1238decryptAllSecrets()decrypts each secret in atry, and the emptycatchat:1233-1236skips any that fail.src/views/SecretList.vue:1247-1250openExport()hands only the decrypted list to the export dialog. No count of skipped secrets travels with it.src/views/SecretList.vue:1259-1262openCxp()does the same for the CXP transfer.keepiq/src/views/SecretList.vue
Lines 1223 to 1250 in b5727e0
The comment names a blocked or revoked suite as the reason. That is exactly the case where a user most needs to know what the file does not hold.
Specified fix:
openspec/changes/portability-export-choice-and-restore-fidelity, design D5 and task 1.3 (the dialog shows how many secrets were left out and lets the user cancel).Found by the OpenSpec pass on 27 Sep 2026 and re-read at b5727e0 on 28 Sep.
Live check: make one secret undecryptable (for example, encrypted to a suite that is now revoked), export the vault, and compare the number of secrets in the file with the number in the list.