mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-05-14 19:07:28 +08:00
Merge 46566848bb into 3b2f6fd149
This commit is contained in:
commit
d6af85be35
@ -333,7 +333,7 @@ def _reject_simple_form_content_type(request):
|
|||||||
Applied ONLY to POST handlers that do not consume a request body (e.g.,
|
Applied ONLY to POST handlers that do not consume a request body (e.g.,
|
||||||
/snapshot/save, /manager/queue/{reset,start,update_comfyui},
|
/snapshot/save, /manager/queue/{reset,start,update_comfyui},
|
||||||
/manager/reboot). These are vulnerable to cross-origin <form method=POST>
|
/manager/reboot). These are vulnerable to cross-origin <form method=POST>
|
||||||
attacks because the handler accepts the request without parsing any body —
|
attacks because the handler accepts the request without parsing any body,
|
||||||
the attacker needs no ability to forge a valid payload, only to point a
|
the attacker needs no ability to forge a valid payload, only to point a
|
||||||
hidden form at the URL.
|
hidden form at the URL.
|
||||||
|
|
||||||
@ -342,8 +342,8 @@ def _reject_simple_form_content_type(request):
|
|||||||
body because the browser refuses to send ``application/json`` without a
|
body because the browser refuses to send ``application/json`` without a
|
||||||
CORS preflight, which this server does not answer.
|
CORS preflight, which this server does not answer.
|
||||||
|
|
||||||
DO NOT add this gate to body-reading handlers — redundant and UX-breaking.
|
DO NOT add this gate to body-reading handlers, redundant and UX-breaking.
|
||||||
DO NOT remove this gate from no-body handlers — this is the bypass vector.
|
DO NOT remove this gate from no-body handlers, this is the bypass vector.
|
||||||
|
|
||||||
aiohttp's ``request.content_type`` normalizes the header (lower-cases,
|
aiohttp's ``request.content_type`` normalizes the header (lower-cases,
|
||||||
strips parameters), so ``multipart/form-data; boundary=----X`` is compared
|
strips parameters), so ``multipart/form-data; boundary=----X`` is compared
|
||||||
@ -353,8 +353,12 @@ def _reject_simple_form_content_type(request):
|
|||||||
web.Response(status=400) when the request has a simple-form
|
web.Response(status=400) when the request has a simple-form
|
||||||
Content-Type that must be rejected. None when the request is allowed
|
Content-Type that must be rejected. None when the request is allowed
|
||||||
to proceed (no Content-Type, application/json, or any non-simple
|
to proceed (no Content-Type, application/json, or any non-simple
|
||||||
Content-Type).
|
Content-Type, or no request object, internal caller).
|
||||||
"""
|
"""
|
||||||
|
# Internal callers (e.g. legacy-UI batch flows) invoke route handlers
|
||||||
|
# directly with request=None; there is no Content-Type to gate.
|
||||||
|
if request is None:
|
||||||
|
return None
|
||||||
if request.content_type in _SIMPLE_FORM_CONTENT_TYPES:
|
if request.content_type in _SIMPLE_FORM_CONTENT_TYPES:
|
||||||
return web.Response(
|
return web.Response(
|
||||||
status=400,
|
status=400,
|
||||||
|
|||||||
@ -23,7 +23,7 @@ from aiohttp.test_utils import TestClient, TestServer
|
|||||||
|
|
||||||
# Parse the helper from manager_server.py without importing it, to avoid
|
# Parse the helper from manager_server.py without importing it, to avoid
|
||||||
# pulling in the full ComfyUI/PromptServer stack. Note: we intentionally do
|
# pulling in the full ComfyUI/PromptServer stack. Note: we intentionally do
|
||||||
# NOT add the `glob/` directory to sys.path — the dir name would shadow
|
# NOT add the `glob/` directory to sys.path, the dir name would shadow
|
||||||
# Python's stdlib `glob` module and break pytest collection.
|
# Python's stdlib `glob` module and break pytest collection.
|
||||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
@ -116,6 +116,12 @@ class ContentTypeRejectionTest(unittest.TestCase):
|
|||||||
r = self._post({"Content-Type": "application/json"})
|
r = self._post({"Content-Type": "application/json"})
|
||||||
self.assertEqual(r.status, 200)
|
self.assertEqual(r.status, 200)
|
||||||
|
|
||||||
|
def test_none_request_allowed(self):
|
||||||
|
# Internal callers (e.g. legacy-UI batch flows) invoke route handlers
|
||||||
|
# directly with request=None; helper must not raise AttributeError.
|
||||||
|
# Regression test for issue #2843.
|
||||||
|
self.assertIsNone(_reject_simple_form_content_type(None))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user