From 711d6018bfca61bedb28f4db0df4537ae33056c1 Mon Sep 17 00:00:00 2001 From: QualiaRain <44004657+QualiaRain@users.noreply.github.com> Date: Sat, 13 Jun 2026 00:21:25 -0400 Subject: [PATCH] fix(api): IP-adapter mask accumulation, null params, colon-in-password, raw allowed path generate.py: p.ip_adapter_masks was reinitialized inside the per-adapter loop, discarding all but the last adapter's masks; move it beside the other accumulators. process.py: req.params is dict|None, so a null params body crashed .items() in post_preprocess/post_mask. api.py: split(':') without maxsplit broke auth/auth-file entries whose password contains a colon. gallery.py: allowed_paths stored quote(path) but the membership check and path guards use the raw path, causing duplicate accumulation and an ineffective whitelist; also drop the unused FastAPI import (pylint W0611 surfaced when this file is linted). Co-Authored-By: Claude --- modules/api/api.py | 4 ++-- modules/api/gallery.py | 3 +-- modules/api/generate.py | 2 +- modules/api/process.py | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index bb7d78bd6..86c67ae84 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -17,12 +17,12 @@ class Api: self.credentials = {} if shared.cmd_opts.auth: for auth in shared.cmd_opts.auth.split(","): - user, password = auth.split(":") + user, password = auth.split(":", 1) self.credentials[user.replace('"', '').strip()] = password.replace('"', '').strip() if shared.cmd_opts.auth_file: with open(shared.cmd_opts.auth_file, encoding="utf8") as file: for line in file.readlines(): - user, password = line.split(":") + user, password = line.split(":", 1) self.credentials[user.replace('"', '').strip()] = password.replace('"', '').strip() self.router = APIRouter() if shared.cmd_opts.docs: diff --git a/modules/api/gallery.py b/modules/api/gallery.py index b585ad896..5c38ea8a3 100644 --- a/modules/api/gallery.py +++ b/modules/api/gallery.py @@ -3,7 +3,6 @@ import os import time import base64 from urllib.parse import quote, unquote -from fastapi import FastAPI from fastapi.responses import JSONResponse from starlette.websockets import WebSocket, WebSocketState from pydantic import BaseModel, Field # pylint: disable=no-name-in-module @@ -173,7 +172,7 @@ def register_api(api): # register api unique_folders.append(f) if shared.demo is not None and path not in shared.demo.allowed_paths: debug(f'Browser folders allow: {path}') - shared.demo.allowed_paths.append(quote(path)) + shared.demo.allowed_paths.append(path) debug(f'Browser folders: {unique_folders}') return JSONResponse(content=unique_folders) diff --git a/modules/api/generate.py b/modules/api/generate.py index 678292922..783a78523 100644 --- a/modules/api/generate.py +++ b/modules/api/generate.py @@ -70,6 +70,7 @@ class APIGenerate: p.ip_adapter_starts = [] p.ip_adapter_ends = [] p.ip_adapter_images = [] + p.ip_adapter_masks = [] for ipadapter in request.ip_adapter: if not ipadapter.images or len(ipadapter.images) == 0: continue @@ -79,7 +80,6 @@ class APIGenerate: p.ip_adapter_starts.append(ipadapter.start) p.ip_adapter_ends.append(ipadapter.end) p.ip_adapter_images.append([helpers.decode_base64_to_image(x) for x in ipadapter.images]) - p.ip_adapter_masks = [] if ipadapter.masks: p.ip_adapter_masks.append([helpers.decode_base64_to_image(x) for x in ipadapter.masks]) del request.ip_adapter diff --git a/modules/api/process.py b/modules/api/process.py index 9c3925a51..1abf3950b 100644 --- a/modules/api/process.py +++ b/modules/api/process.py @@ -76,7 +76,7 @@ class APIProcess: if processor is None or processor.processor_id != req.model: with self.queue_lock: processor = processors.Processor(req.model) - for k, v in req.params.items(): + for k, v in (req.params or {}).items(): if k not in processors.config[processor.processor_id]['params']: return JSONResponse(status_code=400, content={"error": f"Processor invalid parameter: id={req.model} {k}={v}"}) jobid = shared.state.begin('API-PRE', api=True) @@ -102,7 +102,7 @@ class APIProcess: return JSONResponse(status_code=400, content={"error": f"Mask type not found: id={req.type}"}) image = decode_base64_to_image(req.image) mask = decode_base64_to_image(req.mask) if req.mask else None - for k, v in req.params.items(): + for k, v in (req.params or {}).items(): if not hasattr(masking.opts, k): return JSONResponse(status_code=400, content={"error": f"Mask invalid parameter: {k}={v}"}) else: