From 3ab3516e46703376ebcb3d24a794e8405962398e Mon Sep 17 00:00:00 2001 From: comfyanonymous Date: Sun, 8 Sep 2024 18:08:28 -0400 Subject: [PATCH 1/6] By default only accept requests where origin header matches the host. Browsers are dumb and let any website do requests to localhost this should prevent this without breaking things. CORS prevents the javascript from reading the response but they can still write it. At the moment this is only enabled when the --enable-cors-header argument is not used. --- server.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/server.py b/server.py index 3611880da..4d78ee571 100644 --- a/server.py +++ b/server.py @@ -80,6 +80,27 @@ def create_cors_middleware(allowed_origin: str): return cors_middleware +def create_origin_only_middleware(): + @web.middleware + async def origin_only_middleware(request: web.Request, handler): + if request.method == "OPTIONS": + response = web.Response() + else: + response = await handler(request) + + if 'Host' in request.headers and 'Origin' in request.headers: + host = request.headers['Host'] + origin = request.headers['Origin'] + host_domain = host.lower() + origin_domain = urllib.parse.urlparse(origin).netloc.lower() + if host_domain != origin_domain: + logging.warning("WARNING: request with non matching host and origin {} != {}, returning 403".format(host_domain, origin_domain)) + return web.Response(status=403) + + return response + + return origin_only_middleware + class PromptServer(): def __init__(self, loop): PromptServer.instance = self @@ -99,6 +120,8 @@ class PromptServer(): middlewares = [cache_control] if args.enable_cors_header: middlewares.append(create_cors_middleware(args.enable_cors_header)) + else: + middlewares.append(create_origin_only_middleware()) max_upload_size = round(args.max_upload_size * 1024 * 1024) self.app = web.Application(client_max_size=max_upload_size, middlewares=middlewares) From cbaac71bf55c55e0bb4b878708fddece35073122 Mon Sep 17 00:00:00 2001 From: comfyanonymous Date: Sun, 8 Sep 2024 19:35:23 -0400 Subject: [PATCH 2/6] Fix issue with last commit. --- server.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 4d78ee571..ccb8fe812 100644 --- a/server.py +++ b/server.py @@ -83,11 +83,6 @@ def create_cors_middleware(allowed_origin: str): def create_origin_only_middleware(): @web.middleware async def origin_only_middleware(request: web.Request, handler): - if request.method == "OPTIONS": - response = web.Response() - else: - response = await handler(request) - if 'Host' in request.headers and 'Origin' in request.headers: host = request.headers['Host'] origin = request.headers['Origin'] @@ -97,6 +92,11 @@ def create_origin_only_middleware(): logging.warning("WARNING: request with non matching host and origin {} != {}, returning 403".format(host_domain, origin_domain)) return web.Response(status=403) + if request.method == "OPTIONS": + response = web.Response() + else: + response = await handler(request) + return response return origin_only_middleware From 967867d48c29666630edfa10a1ab711217e3094e Mon Sep 17 00:00:00 2001 From: Darion Date: Sun, 8 Sep 2024 21:02:32 -0400 Subject: [PATCH 3/6] fix: url decode filename from API (#4801) --- app/user_manager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/user_manager.py b/app/user_manager.py index 53dff18b7..95ad157c3 100644 --- a/app/user_manager.py +++ b/app/user_manager.py @@ -5,6 +5,7 @@ import uuid import glob import shutil from aiohttp import web +from urllib import parse from comfy.cli_args import args from folder_paths import user_directory from .app_settings import AppSettings @@ -59,6 +60,10 @@ class UserManager(): return None if file is not None: + # Check if filename is url encoded + if "%" in file: + file = parse.unquote(file) + # prevent leaving /{type}/{user} path = os.path.abspath(os.path.join(user_root, file)) if os.path.commonpath((user_root, path)) != user_root: From e3b0402bb792c528a8b2fadd11d35604bafc0d7b Mon Sep 17 00:00:00 2001 From: comfyanonymous Date: Mon, 9 Sep 2024 01:04:03 -0400 Subject: [PATCH 4/6] Ignore origin domain when it's empty. --- server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index ccb8fe812..4f8053fc6 100644 --- a/server.py +++ b/server.py @@ -88,9 +88,10 @@ def create_origin_only_middleware(): origin = request.headers['Origin'] host_domain = host.lower() origin_domain = urllib.parse.urlparse(origin).netloc.lower() - if host_domain != origin_domain: - logging.warning("WARNING: request with non matching host and origin {} != {}, returning 403".format(host_domain, origin_domain)) - return web.Response(status=403) + if len(host_domain) > 0 and len(origin_domain) > 0: + if host_domain != origin_domain: + logging.warning("WARNING: request with non matching host and origin {} != {}, returning 403".format(host_domain, origin_domain)) + return web.Response(status=403) if request.method == "OPTIONS": response = web.Response() From 619263d4a6a5d669af780c5cb5092051ffbe9784 Mon Sep 17 00:00:00 2001 From: "Alex \"mcmonkey\" Goodwin" <4000772+mcmonkey4eva@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:55:51 +0900 Subject: [PATCH 5/6] allow current timestamp in save image prefix (#4030) --- folder_paths.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/folder_paths.py b/folder_paths.py index 74a7d527c..b154448fc 100644 --- a/folder_paths.py +++ b/folder_paths.py @@ -257,9 +257,17 @@ def get_save_image_path(filename_prefix: str, output_dir: str, image_width=0, im def compute_vars(input: str, image_width: int, image_height: int) -> str: input = input.replace("%width%", str(image_width)) input = input.replace("%height%", str(image_height)) + now = time.localtime() + input = input.replace("%year%", str(now.tm_year)) + input = input.replace("%month%", str(now.tm_mon).zfill(2)) + input = input.replace("%day%", str(now.tm_mday).zfill(2)) + input = input.replace("%hour%", str(now.tm_hour).zfill(2)) + input = input.replace("%minute%", str(now.tm_min).zfill(2)) + input = input.replace("%second%", str(now.tm_sec).zfill(2)) return input - filename_prefix = compute_vars(filename_prefix, image_width, image_height) + if "%" in filename_prefix: + filename_prefix = compute_vars(filename_prefix, image_width, image_height) subfolder = os.path.dirname(os.path.normpath(filename_prefix)) filename = os.path.basename(os.path.normpath(filename_prefix)) From e0b41243b413c841d84f2e85d7ba3e71382febf4 Mon Sep 17 00:00:00 2001 From: comfyanonymous Date: Mon, 9 Sep 2024 03:18:17 -0400 Subject: [PATCH 6/6] Fix issue where sometimes origin doesn't contain the port. --- server.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index 4f8053fc6..93147f6c5 100644 --- a/server.py +++ b/server.py @@ -87,7 +87,12 @@ def create_origin_only_middleware(): host = request.headers['Host'] origin = request.headers['Origin'] host_domain = host.lower() - origin_domain = urllib.parse.urlparse(origin).netloc.lower() + parsed = urllib.parse.urlparse(origin) + origin_domain = parsed.netloc.lower() + if parsed.port is None: #if origin doesn't have a port strip it from the host to handle weird browsers + result = urllib.parse.urlsplit('//' + host_domain) + host_domain = result.hostname + if len(host_domain) > 0 and len(origin_domain) > 0: if host_domain != origin_domain: logging.warning("WARNING: request with non matching host and origin {} != {}, returning 403".format(host_domain, origin_domain))