Matrix: avoid eager DM SAS starts

This commit is contained in:
Gustavo Madeira Santana 2026-03-13 15:25:20 +00:00
parent 37583bb511
commit 36b10d71ca
No known key found for this signature in database
3 changed files with 55 additions and 2 deletions

View File

@ -274,6 +274,9 @@ export class MatrixCryptoBootstrapper<TRawEvent extends MatrixRawEvent> {
// Track incoming requests; verification lifecycle decisions live in the
// verification manager so acceptance/start/dedupe share one code path.
// Remote-user verifications are only auto-accepted. The human-operated
// client must explicitly choose "Verify by emoji" so we do not race a
// second SAS start from the bot side and end up with mismatched keys.
crypto.on(CryptoEvent.VerificationRequestReceived, async (request) => {
const verificationRequest = request as MatrixVerificationRequestLike;
try {

View File

@ -256,7 +256,7 @@ describe("MatrixVerificationManager", () => {
});
});
it("auto-starts inbound SAS when request becomes ready without a verifier", async () => {
it("does not auto-start non-self inbound SAS when request becomes ready without a verifier", async () => {
const verify = vi.fn(async () => {});
const verifier = new MockVerifier(
{
@ -276,8 +276,55 @@ describe("MatrixVerificationManager", () => {
verify,
);
const request = new MockVerificationRequest({
transactionId: "txn-auto-start-sas",
transactionId: "txn-no-auto-start-dm-sas",
initiatedByMe: false,
isSelfVerification: false,
verifier: undefined,
});
request.startVerification = vi.fn(async (_method: string) => {
request.phase = VerificationPhase.Started;
request.verifier = verifier;
return verifier;
});
const manager = new MatrixVerificationManager();
const tracked = manager.trackVerificationRequest(request);
request.phase = VerificationPhase.Ready;
request.emit(VerificationRequestEvent.Change);
await vi.waitFor(() => {
expect(manager.listVerifications().find((item) => item.id === tracked.id)?.phase).toBe(
VerificationPhase.Ready,
);
});
expect(request.startVerification).not.toHaveBeenCalled();
expect(verify).not.toHaveBeenCalled();
expect(manager.listVerifications().find((item) => item.id === tracked.id)?.hasSas).toBe(false);
});
it("auto-starts self verification SAS when request becomes ready without a verifier", async () => {
const verify = vi.fn(async () => {});
const verifier = new MockVerifier(
{
sas: {
decimal: [1234, 5678, 9012],
emoji: [
["gift", "Gift"],
["rocket", "Rocket"],
["butterfly", "Butterfly"],
],
},
confirm: vi.fn(async () => {}),
mismatch: vi.fn(),
cancel: vi.fn(),
},
null,
verify,
);
const request = new MockVerificationRequest({
transactionId: "txn-auto-start-self-sas",
initiatedByMe: false,
isSelfVerification: true,
verifier: undefined,
});
request.startVerification = vi.fn(async (_method: string) => {

View File

@ -313,6 +313,9 @@ export class MatrixVerificationManager {
if (this.readRequestValue(session.request, () => session.request.initiatedByMe, true)) {
return;
}
if (!this.readRequestValue(session.request, () => session.request.isSelfVerification, false)) {
return;
}
const phase = this.readRequestValue(
session.request,
() => session.request.phase,