From c8dfc74d41f9d9c7bacca57c3e334b9f12fecd45 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 23 Jul 2026 01:48:14 +0000 Subject: [PATCH] Improve pin message validations. --- .../api/messages/EnvelopeContentValidator.kt | 2 +- .../messages/EnvelopeContentValidatorTest.kt | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/lib/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidator.kt b/lib/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidator.kt index de94204266..688a769269 100644 --- a/lib/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidator.kt +++ b/lib/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidator.kt @@ -184,7 +184,7 @@ object EnvelopeContentValidator { return Result.Invalid("[DataMessage] Invalid poll vote!") } - if (dataMessage.pinMessage != null && (dataMessage.pinMessage.targetAuthorAciBinary.isNullOrInvalidAci() || dataMessage.pinMessage.targetSentTimestamp == null || (dataMessage.pinMessage.pinDurationSeconds == null && dataMessage.pinMessage.pinDurationForever == null))) { + if (dataMessage.pinMessage != null && (dataMessage.pinMessage.targetAuthorAciBinary.isNullOrInvalidAci() || dataMessage.pinMessage.targetSentTimestamp == null || (dataMessage.pinMessage.pinDurationSeconds == null && dataMessage.pinMessage.pinDurationForever != true))) { return Result.Invalid("[DataMessage] Invalid pin message!") } diff --git a/lib/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidatorTest.kt b/lib/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidatorTest.kt index ce61d0cbec..9ba6c54369 100644 --- a/lib/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidatorTest.kt +++ b/lib/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/EnvelopeContentValidatorTest.kt @@ -305,6 +305,106 @@ class EnvelopeContentValidatorTest { assert(result is EnvelopeContentValidator.Result.Valid) } + @Test + fun `validate - ensure pin messages without a valid aci are marked invalid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = "bad".toByteArray().toByteString(), + targetSentTimestamp = 1000, + pinDurationSeconds = 60 + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Invalid) + } + + @Test + fun `validate - ensure pin messages without a target timestamp are marked invalid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = OTHER_ACI.toByteString(), + pinDurationSeconds = 60 + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Invalid) + } + + @Test + fun `validate - ensure pin messages without a pin duration are marked invalid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = OTHER_ACI.toByteString(), + targetSentTimestamp = 1000 + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Invalid) + } + + @Test + fun `validate - ensure pin messages with pinDurationForever set to false but no seconds are marked invalid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = OTHER_ACI.toByteString(), + targetSentTimestamp = 1000, + pinDurationForever = false + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Invalid) + } + + @Test + fun `validate - ensure pin messages with a pin duration in seconds are marked valid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = OTHER_ACI.toByteString(), + targetSentTimestamp = 1000, + pinDurationSeconds = 60 + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Valid) + } + + @Test + fun `validate - ensure pin messages with pinDurationForever set to true are marked valid`() { + val content = Content( + dataMessage = DataMessage( + timestamp = 1234, + pinMessage = DataMessage.PinMessage( + targetAuthorAciBinary = OTHER_ACI.toByteString(), + targetSentTimestamp = 1000, + pinDurationForever = true + ) + ) + ) + + val result = EnvelopeContentValidator.validate(Envelope(clientTimestamp = 1234), content, SELF_ACI, CiphertextMessage.WHISPER_TYPE) + assert(result is EnvelopeContentValidator.Result.Valid) + } + @Test fun `validate - ensure quote body range mentions with invalid aci are marked invalid`() { val content = Content(