diff --git a/ts/services/storage.ts b/ts/services/storage.ts index 3cf3a47508..4d69b86455 100644 --- a/ts/services/storage.ts +++ b/ts/services/storage.ts @@ -167,6 +167,20 @@ async function generateManifest( continue; } + const validationError = conversation.validate(); + if (validationError) { + if (conversation.get('storageID')) { + log.warn( + 'storageService.generateManifest: skipping contact', + conversation.idForLogging(), + 'due to local validation error', + validationError + ); + conversation.unset('storageID'); + } + continue; + } + storageRecord = new Proto.StorageRecord(); // eslint-disable-next-line no-await-in-loop storageRecord.contact = await toContactRecord(conversation); diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index 87bacb93e9..24d3b833d8 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -35,9 +35,12 @@ import { } from '../util/universalExpireTimer'; import { ourProfileKeyService } from './ourProfileKey'; import { isGroupV1, isGroupV2 } from '../util/whatTypeOfConversation'; +import { isValidUuid } from '../types/UUID'; +import type { ConversationAttributesType } from '../model-types.d'; import * as preferredReactionEmoji from '../reactions/preferredReactionEmoji'; import { SignalService as Proto } from '../protobuf'; import * as log from '../logging/log'; +import type { WhatIsThis } from '../window.d'; const { updateConversation } = dataInterface; @@ -730,6 +733,25 @@ export async function mergeContactRecord( return false; } + if (!isValidUuid(uuid)) { + return false; + } + + const c = new window.Whisper.Conversation(({ + e164, + uuid, + type: 'private', + } as Partial) as WhatIsThis); + + const validationError = c.validate(); + if (validationError) { + log.error( + 'storageService.mergeContactRecord: invalid contact', + validationError + ); + return false; + } + const id = window.ConversationController.ensureContactIds({ e164, uuid,