fix(matrix): allow secret storage recreation during repair bootstrap

The gateway repair path calls forceResetCrossSigning but does not pass
allowSecretStorageRecreateWithoutRecoveryKey. When a device loses its
recovery key the repair creates new cross-signing keys but cannot
persist them in secret storage. On next restart the gateway fails again
with "getSecretStorageKey callback returned falsey".

Pass allowSecretStorageRecreateWithoutRecoveryKey: true in the repair
bootstrap call only. The initial conservative bootstrap remains
unchanged so operators are notified when secret storage becomes
inaccessible.
This commit is contained in:
Alejandro Martinez
2026-04-02 20:08:04 +02:00
committed by Gustavo Madeira Santana
parent 739ed1bf29
commit 7bd6ba09a7
2 changed files with 6 additions and 0 deletions

View File

@@ -1050,6 +1050,7 @@ describe("MatrixClient crypto bootstrapping", () => {
expect(bootstrapSpy).toHaveBeenCalledTimes(2);
expect((bootstrapSpy.mock.calls as unknown[][])[1]?.[1] ?? {}).toEqual({
forceResetCrossSigning: true,
allowSecretStorageRecreateWithoutRecoveryKey: true,
strict: true,
});
});

View File

@@ -465,8 +465,13 @@ export class MatrixClient {
);
} else if (this.password?.trim()) {
try {
// The repair path already force-resets cross-signing; allow secret storage
// recreation so the new keys can be persisted. Without this, a device that
// lost its recovery key enters a permanent failure loop because the new
// cross-signing keys have nowhere to be stored.
const repaired = await cryptoBootstrapper.bootstrap(crypto, {
forceResetCrossSigning: true,
allowSecretStorageRecreateWithoutRecoveryKey: true,
strict: true,
});
if (repaired.crossSigningPublished && repaired.ownDeviceVerified !== false) {