mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-03-28 20:43:32 +08:00
security: handle Windows backslash path traversal in filename validation
Normalize backslashes to forward slashes before checking for path traversal patterns, preventing attacks like `folder\..\secret` that bypass forward-slash-only checks on Windows. Addresses review feedback from light-and-ray on PR #12353. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dd9f4d1a32
commit
ae575a8670
10
server.py
10
server.py
@ -441,8 +441,9 @@ class PromptServer():
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
# validation for security: prevent accessing arbitrary path
|
# validation for security: prevent accessing arbitrary path
|
||||||
# Check for path traversal patterns (../ or /..) but allow consecutive dots in filename
|
# Normalize backslashes to forward slashes to handle Windows-style path traversal (e.g., folder\..\secret)
|
||||||
if filename[0] == '/' or '/..' in filename or filename.startswith('..'):
|
normalized = filename.replace('\\', '/')
|
||||||
|
if normalized[0] == '/' or '/..' in normalized or normalized.startswith('..'):
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
if output_dir is None:
|
if output_dir is None:
|
||||||
@ -486,8 +487,9 @@ class PromptServer():
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
# validation for security: prevent accessing arbitrary path
|
# validation for security: prevent accessing arbitrary path
|
||||||
# Check for path traversal patterns (../ or /..) but allow consecutive dots in filename
|
# Normalize backslashes to forward slashes to handle Windows-style path traversal (e.g., folder\..\secret)
|
||||||
if filename[0] == '/' or '/..' in filename or filename.startswith('..'):
|
normalized = filename.replace('\\', '/')
|
||||||
|
if normalized[0] == '/' or '/..' in normalized or normalized.startswith('..'):
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
if output_dir is None:
|
if output_dir is None:
|
||||||
|
|||||||
@ -35,8 +35,9 @@ class TestViewEndpointSecurity(AioHTTPTestCase):
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
# validation for security: prevent accessing arbitrary path
|
# validation for security: prevent accessing arbitrary path
|
||||||
# Check for path traversal patterns (../ or /..) but allow consecutive dots in filename
|
# Normalize backslashes to forward slashes to handle Windows-style path traversal
|
||||||
if filename[0] == '/' or '/..' in filename or filename.startswith('..'):
|
normalized = filename.replace('\\', '/')
|
||||||
|
if normalized[0] == '/' or '/..' in normalized or normalized.startswith('..'):
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
# For testing, just check if file exists in test directory
|
# For testing, just check if file exists in test directory
|
||||||
@ -112,3 +113,27 @@ class TestViewEndpointSecurity(AioHTTPTestCase):
|
|||||||
|
|
||||||
resp = await self.client.request("GET", "/view?filename=my..file..name.png")
|
resp = await self.client.request("GET", "/view?filename=my..file..name.png")
|
||||||
assert resp.status == 200, "Should allow dots in middle of filename"
|
assert resp.status == 200, "Should allow dots in middle of filename"
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_blocks_backslash_path_traversal(self):
|
||||||
|
"""Test that Windows-style backslash path traversal (\\..) is blocked"""
|
||||||
|
resp = await self.client.request("GET", "/view?filename=folder%5C..%5Csecret")
|
||||||
|
assert resp.status == 400, "Should block backslash path traversal"
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_blocks_backslash_dotdot_at_start(self):
|
||||||
|
"""Test that backslash path traversal starting with ..\\ is blocked"""
|
||||||
|
resp = await self.client.request("GET", "/view?filename=..%5Cetc%5Cpasswd")
|
||||||
|
assert resp.status == 400, "Should block ..\\ path traversal at start"
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_blocks_mixed_slash_backslash_traversal(self):
|
||||||
|
"""Test that mixed forward/backslash path traversal is blocked"""
|
||||||
|
resp = await self.client.request("GET", "/view?filename=folder/..%5Csecret")
|
||||||
|
assert resp.status == 400, "Should block mixed slash/backslash path traversal"
|
||||||
|
|
||||||
|
@unittest_run_loop
|
||||||
|
async def test_blocks_backslash_absolute_path(self):
|
||||||
|
"""Test that Windows absolute paths with backslash are blocked (e.g., C:\\)"""
|
||||||
|
resp = await self.client.request("GET", "/view?filename=%5Cetc%5Cpasswd")
|
||||||
|
assert resp.status == 400, "Should block backslash absolute paths"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user