[GH-ISSUE #1125] Path Traversal Vulnerability #480

Closed
opened 2026-10-27 21:18:06 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @Arashimu on GitHub (Oct 8, 2024).
Original GitHub issue: https://github.com/Comfy-Org/ComfyUI-Manager/issues/1125

The plugin of ComfyUI: ComfyUI-Manager allows for arbitrary file overwrite.

RCA:

@PromptServer.instance.routes.post("/customnode/install")
async def install_custom_node(request):
    if not is_allowed_security_level('middle'):
        print(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
        return web.Response(status=403)

    json_data = await request.json()

    risky_level = await get_risky_level(json_data['files'])
    if not is_allowed_security_level(risky_level):        # [1] If secure_level is set to weak 
        print(SECURITY_MESSAGE_GENERAL)
        return web.Response(status=404)

    install_type = json_data['install_type']

    print(f"Install custom node '{json_data['title']}'")

    res = False

    if len(json_data['files']) == 0:
        return web.Response(status=400)

    if install_type == "unzip":
        res = unzip_install(json_data['files'])

    if install_type == "copy":							# [2] If attacker fake a copy request
        js_path_name = json_data['js_path'] if 'js_path' in json_data else '.'
        res = copy_install(json_data['files'], js_path_name)

    elif install_type == "git-clone":
        res = core.gitclone_install(json_data['files'])

    if 'pip' in json_data:
        for pname in json_data['pip']:
            pkg = core.remap_pip_package(pname)
            install_cmd = [sys.executable, "-m", "pip", "install", pkg]
            core.try_install_script(json_data['files'][0], ".", install_cmd)

    core.clear_pip_cache()

    if res:
        print(f"After restarting ComfyUI, please refresh the browser.")
        return web.json_response({}, content_type='application/json')

    return web.Response(status=400)

[1] If a user set the secure_level to weak

[2] then the attacker can fake a copy request with a arbitrary url

def copy_install(files, js_path_name=None):
    for url in files:
        if url.endswith("/"):
            url = url[:-1]
        try:
            filename = os.path.basename(url)
            if url.endswith(".py"):
                download_url(url, core.custom_nodes_path, filename)
            else:				# [3] If not .py file and fake a js_path_name param
                path = os.path.join(core.js_path, js_path_name) if js_path_name is not None else core.js_path
                if not os.path.exists(path):
                    os.makedirs(path)
                download_url(url, path, filename)

        except Exception as e:
            print(f"Install(copy) error: {url} / {e}", file=sys.stderr)
            return False

    print("Installation was successful.")
    return True

[3] notice that the param js_path_name is not checked, so lead to arbitrary file overwrite.

before run the poc, the layout as follow:

ComfyUI1

then I run the command python -m http.server to start a http server and use Yakit to send a fake request:

ComfyUI2

finally trigger a arbitrary file overwrite:

ComfyUI2

Although this can only be executed at a low security level, there is still a possibility of risk occurring.

Originally created by @Arashimu on GitHub (Oct 8, 2024). Original GitHub issue: https://github.com/Comfy-Org/ComfyUI-Manager/issues/1125 The plugin of ComfyUI: ComfyUI-Manager allows for arbitrary file overwrite. RCA: ``` python @PromptServer.instance.routes.post("/customnode/install") async def install_custom_node(request): if not is_allowed_security_level('middle'): print(SECURITY_MESSAGE_MIDDLE_OR_BELOW) return web.Response(status=403) json_data = await request.json() risky_level = await get_risky_level(json_data['files']) if not is_allowed_security_level(risky_level): # [1] If secure_level is set to weak print(SECURITY_MESSAGE_GENERAL) return web.Response(status=404) install_type = json_data['install_type'] print(f"Install custom node '{json_data['title']}'") res = False if len(json_data['files']) == 0: return web.Response(status=400) if install_type == "unzip": res = unzip_install(json_data['files']) if install_type == "copy": # [2] If attacker fake a copy request js_path_name = json_data['js_path'] if 'js_path' in json_data else '.' res = copy_install(json_data['files'], js_path_name) elif install_type == "git-clone": res = core.gitclone_install(json_data['files']) if 'pip' in json_data: for pname in json_data['pip']: pkg = core.remap_pip_package(pname) install_cmd = [sys.executable, "-m", "pip", "install", pkg] core.try_install_script(json_data['files'][0], ".", install_cmd) core.clear_pip_cache() if res: print(f"After restarting ComfyUI, please refresh the browser.") return web.json_response({}, content_type='application/json') return web.Response(status=400) ``` [1] If a user set the secure_level to weak [2] then the attacker can fake a copy request with a arbitrary url ``` python def copy_install(files, js_path_name=None): for url in files: if url.endswith("/"): url = url[:-1] try: filename = os.path.basename(url) if url.endswith(".py"): download_url(url, core.custom_nodes_path, filename) else: # [3] If not .py file and fake a js_path_name param path = os.path.join(core.js_path, js_path_name) if js_path_name is not None else core.js_path if not os.path.exists(path): os.makedirs(path) download_url(url, path, filename) except Exception as e: print(f"Install(copy) error: {url} / {e}", file=sys.stderr) return False print("Installation was successful.") return True ``` [3] notice that the param `js_path_name` is not checked, so lead to arbitrary file overwrite. before run the poc, the layout as follow: ![ComfyUI1](https://raw.githubusercontent.com/Arashimu/images/main/ComfyUI/2.png) then I run the command `python -m http.server` to start a http server and use Yakit to send a fake request: ![ComfyUI2](https://raw.githubusercontent.com/Arashimu/images/main/ComfyUI/1.png) finally trigger a arbitrary file overwrite: ![ComfyUI2](https://raw.githubusercontent.com/Arashimu/images/main/ComfyUI/3.png) Although this can only be executed at a low security level, there is still a possibility of risk occurring.
Author
Owner

@ltdrdata commented on GitHub (Oct 8, 2024):

This is fixed.
Thank you for the report.

<!-- gh-comment-id:2399434483 --> @ltdrdata commented on GitHub (Oct 8, 2024): This is fixed. Thank you for the report.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Comfy-Org/ComfyUI-Manager#480
No description provided.