Security: guard against path traversal from hostile remotes
Build & Release APK / build (push) Successful in 12m42s
Build & Release APK / build (push) Successful in 12m42s
WebDAV already sanitizes server-supplied names, but SFTP passed entry.name through unfiltered, and the engine had no central guard — a malicious or compromised remote could return '../../x' and (on the JavaFile backend) write outside the sync root. - SyncEngine: isUnsafeSyncPath() rejects empty, absolute, and any '..'-segment path; every file is checked before any read/write/delete (covers all providers). - SftpProvider.listFiles: drop '.'/'..' and names containing path separators. - PathSafetyTest covers traversal, backslash, absolute, and empty cases.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package com.syncflow.domain.sync
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Path-traversal guard: a hostile/compromised remote must not be able to make the engine read
|
||||
* or write outside the sync root via "..", absolute, or separator-smuggled paths.
|
||||
*/
|
||||
class PathSafetyTest {
|
||||
|
||||
@Test fun `normal relative paths are allowed`() {
|
||||
assertFalse(isUnsafeSyncPath("photo.jpg"))
|
||||
assertFalse(isUnsafeSyncPath("sub/dir/photo.jpg"))
|
||||
assertFalse(isUnsafeSyncPath("a.b..c/file.txt")) // ".." only inside a name, not a segment
|
||||
}
|
||||
|
||||
@Test fun `parent-dir traversal is rejected`() {
|
||||
assertTrue(isUnsafeSyncPath(".."))
|
||||
assertTrue(isUnsafeSyncPath("../evil"))
|
||||
assertTrue(isUnsafeSyncPath("a/../../etc/passwd"))
|
||||
assertTrue(isUnsafeSyncPath("sub/../../escape"))
|
||||
}
|
||||
|
||||
@Test fun `backslash traversal is rejected`() {
|
||||
assertTrue(isUnsafeSyncPath("..\\evil"))
|
||||
assertTrue(isUnsafeSyncPath("a\\..\\..\\escape"))
|
||||
}
|
||||
|
||||
@Test fun `absolute and empty paths are rejected`() {
|
||||
assertTrue(isUnsafeSyncPath("/etc/passwd"))
|
||||
assertTrue(isUnsafeSyncPath(""))
|
||||
assertTrue(isUnsafeSyncPath(" "))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user