diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepository.kt index 055fe13f24..80af5011bb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepository.kt @@ -435,7 +435,8 @@ object PlaintextExportRepository { @VisibleForTesting internal fun sanitizeFileName(name: String): String { - return name.replace(Regex("[\\\\/:*?\"<>|]"), "_").trim().take(100) + val sanitized = name.replace(Regex("[\\\\/:*?\"<>|]"), "_").trim().take(100) + return if (sanitized.isEmpty() || sanitized.all { it == '.' }) "chat" else sanitized } private fun ExecutorService.submitTyped(callable: Callable): Future { diff --git a/app/src/test/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepositoryTest.kt b/app/src/test/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepositoryTest.kt index f06a703b7a..35d3a27efb 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepositoryTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/conversation/plaintext/PlaintextExportRepositoryTest.kt @@ -723,6 +723,26 @@ class PlaintextExportRepositoryTest { assertEquals("My Chat Group 2024", PlaintextExportRepository.sanitizeFileName("My Chat Group 2024")) } + @Test + fun `sanitizeFileName rejects dot-only names to prevent path traversal`() { + assertEquals("chat", PlaintextExportRepository.sanitizeFileName(".")) + assertEquals("chat", PlaintextExportRepository.sanitizeFileName("..")) + assertEquals("chat", PlaintextExportRepository.sanitizeFileName("...")) + assertEquals("chat", PlaintextExportRepository.sanitizeFileName(" .. ")) + } + + @Test + fun `sanitizeFileName falls back for empty result`() { + assertEquals("chat", PlaintextExportRepository.sanitizeFileName("")) + assertEquals("chat", PlaintextExportRepository.sanitizeFileName(" ")) + } + + @Test + fun `sanitizeFileName preserves names that merely contain dots`() { + assertEquals("..hidden", PlaintextExportRepository.sanitizeFileName("..hidden")) + assertEquals("my.chat.group", PlaintextExportRepository.sanitizeFileName("my.chat.group")) + } + // ==================== getSenderName tests ==================== @Test