diff --git a/backend/src/main/java/org/raddatz/familienarchiv/importing/MassImportService.java b/backend/src/main/java/org/raddatz/familienarchiv/importing/MassImportService.java index 478b540f..64b09294 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/importing/MassImportService.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/importing/MassImportService.java @@ -329,9 +329,15 @@ public class MassImportService { if (filename == null || filename.isBlank()) return false; if (filename.contains("/")) return false; if (filename.contains("\\")) return false; + if (filename.contains("∕")) return false; // U+2215 DIVISION SLASH + if (filename.contains("/")) return false; // U+FF0F FULLWIDTH SOLIDUS + if (filename.contains("⧵")) return false; // U+29F5 REVERSE SOLIDUS OPERATOR if (filename.contains("..")) return false; if (filename.equals(".")) return false; if (filename.contains("\0")) return false; + // Paths.get() is safe here on Linux for all inputs that passed the checks above; + // it may throw InvalidPathException for OS-specific illegal chars on Windows, + // but those are not reachable in production. if (Paths.get(filename).isAbsolute()) return false; return true; } diff --git a/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java b/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java index 2b43bedf..167b78cd 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java @@ -494,6 +494,24 @@ class MassImportServiceTest { assertThat(result).isTrue(); } + @Test + void isValidImportFilename_returnsFalse_whenFilenameContainsUnicodeDivisionSlash() { + boolean result = ReflectionTestUtils.invokeMethod(service, "isValidImportFilename", "foo∕bar.pdf"); + assertThat(result).isFalse(); + } + + @Test + void isValidImportFilename_returnsFalse_whenFilenameContainsFullwidthSlash() { + boolean result = ReflectionTestUtils.invokeMethod(service, "isValidImportFilename", "foo/bar.pdf"); + assertThat(result).isFalse(); + } + + @Test + void isValidImportFilename_returnsFalse_whenFilenameContainsUnicodeReverseSolidus() { + boolean result = ReflectionTestUtils.invokeMethod(service, "isValidImportFilename", "foo⧵bar.pdf"); + assertThat(result).isFalse(); + } + @Test void processRows_skipsRowAndContinues_whenFilenameIsPathTraversal() { when(documentService.findByOriginalFilename("legitimate.pdf")).thenReturn(Optional.empty());