From f12ff87b8770f199e668a240447172fe41320aee Mon Sep 17 00:00:00 2001 From: Matthieu Date: Wed, 3 Jun 2026 17:02:21 +0200 Subject: [PATCH] =?UTF-8?q?feat(share)=20:=20r=C3=A9solution=20de=20chemin?= =?UTF-8?q?=20SMB=20anti=20path-traversal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Share/Exception/InvalidPathException.php | 9 +++ src/Service/Share/SharePathResolver.php | 44 +++++++++++++ tests/Unit/Service/SharePathResolverTest.php | 64 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 src/Service/Share/Exception/InvalidPathException.php create mode 100644 src/Service/Share/SharePathResolver.php create mode 100644 tests/Unit/Service/SharePathResolverTest.php diff --git a/src/Service/Share/Exception/InvalidPathException.php b/src/Service/Share/Exception/InvalidPathException.php new file mode 100644 index 0000000..49d1280 --- /dev/null +++ b/src/Service/Share/Exception/InvalidPathException.php @@ -0,0 +1,9 @@ +normalizeRelative($relativePath); + + $parts = array_values(array_filter([$base, $relative], static fn (string $p): bool => '' !== $p)); + + return '/'.implode('/', $parts); + } +} diff --git a/tests/Unit/Service/SharePathResolverTest.php b/tests/Unit/Service/SharePathResolverTest.php new file mode 100644 index 0000000..bc344ee --- /dev/null +++ b/tests/Unit/Service/SharePathResolverTest.php @@ -0,0 +1,64 @@ +resolver = new SharePathResolver(); + } + + public function testNormalizeRelativeKeepsSimplePath(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('a/b')); + } + + public function testNormalizeRelativeStripsDotsAndSlashes(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('/a/./b/')); + } + + public function testNormalizeRelativeConvertsBackslashes(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('a\b')); + } + + public function testNormalizeRelativeRejectsParentTraversal(): void + { + $this->expectException(InvalidPathException::class); + $this->resolver->normalizeRelative('a/../b'); + } + + public function testNormalizeRelativeRejectsLeadingParent(): void + { + $this->expectException(InvalidPathException::class); + $this->resolver->normalizeRelative('../etc/passwd'); + } + + public function testFullPathJoinsBaseAndRelative(): void + { + self::assertSame('/Projets/a/b', $this->resolver->fullPath('/Projets', 'a/b')); + } + + public function testFullPathWithEmptyBaseAndEmptyRelativeIsRoot(): void + { + self::assertSame('/', $this->resolver->fullPath('', '')); + } + + public function testFullPathTrimsBaseSlashes(): void + { + self::assertSame('/Projets/a', $this->resolver->fullPath('/Projets/', 'a')); + } +}