From 4e741b92a1d7790a6a3ed03b0b74f528e9535ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Sat, 14 Mar 2026 21:27:52 +0000 Subject: [PATCH] security(backurl): re-sanitize back inside helpers --- app/Support/BackUrl.php | 7 ++++ .../BackUrlSanitizeInsideWithBackTest.php | 36 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/Unit/BackUrlSanitizeInsideWithBackTest.php diff --git a/app/Support/BackUrl.php b/app/Support/BackUrl.php index a91d090..49eea00 100644 --- a/app/Support/BackUrl.php +++ b/app/Support/BackUrl.php @@ -94,6 +94,13 @@ class BackUrl return $path; } + // 防御性:即使调用方声称传入的是 safeBack,这里也再按统一口径过滤一遍。 + // 若不合法,则不拼接 back(避免注入/嵌套 back= 膨胀/外链等风险)。 + $safeBackForLinks = self::sanitizeForLinks((string) $safeBackForLinks); + if ($safeBackForLinks === '') { + return $path; + } + // 仅支持站内相对路径;若调用方传入了异常值,这里不做拼接,直接返回原 path。 if ($path === '' || !str_starts_with($path, '/')) { return $path; diff --git a/tests/Unit/BackUrlSanitizeInsideWithBackTest.php b/tests/Unit/BackUrlSanitizeInsideWithBackTest.php new file mode 100644 index 0000000..4a5d956 --- /dev/null +++ b/tests/Unit/BackUrlSanitizeInsideWithBackTest.php @@ -0,0 +1,36 @@ +assertSame('/admin/site-subscriptions/2', $url); + } + + public function test_with_back_should_drop_nested_back_even_if_caller_passes_it_in(): void + { + $nestedBack = '/admin/platform-orders?back=/admin/xx'; + + $url = BackUrl::withBack('/admin/site-subscriptions/2', $nestedBack); + + $this->assertSame('/admin/site-subscriptions/2', $url); + } + + public function test_with_back_should_keep_safe_back(): void + { + $back = '/admin/platform-orders/2'; + $url = BackUrl::withBack('/admin/site-subscriptions/2', $back); + + $this->assertSame('/admin/site-subscriptions/2?' . Arr::query(['back' => $back]), $url); + } +}