[GH-ISSUE #3169] [Manual review request] ComfyUI-EreNodes 3.3.0+ #1114

Closed
opened 2026-10-27 21:25:54 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @Erehr on GitHub (Aug 15, 2026).
Original GitHub issue: https://github.com/Comfy-Org/ComfyUI-Manager/issues/3169

Node: comfyui-erenodes · Repo: https://github.com/Erehr/ComfyUI-EreNodes

Note

Versions 3.3.0, 3.4.0 and 3.5.0 are marked Flagged. Every finding is info severity and every one is a pattern match with no security meaning. I would like the flags cleared.

https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.3.0
https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.4.0
https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.5.0

Findings

Version Finding Location
3.3.0–3.5.0 python_network_operations web/prompt.js, web/prompt_autocomplete.js, web/js/contextmenu.js
3.4.0, 3.5.0 database connection → T1005 Data from Local System py/tag_index.py
3.4.0, 3.5.0 network operation → T1041/T1048 Exfiltration scripts/animadex_to_tag_groups.py
3.4.0, 3.5.0 environment variable read scripts/animadex_to_tag_groups.py

1. .connect() and .bind() in .js files → python_network_operations

A Python network ruleset is being run against JavaScript.

  • originNode.connect(...) is the LiteGraph canvas API, re-wiring graph links when a node is converted to another node type. No socket, no URL.
  • this.onKeyDown.bind(this) and this.close.bind(this) are the standard idiom for keeping this in a DOM event handler.

.connect() and .bind() are two of the most common method names in browser and canvas JavaScript and carry no network meaning there.

2. sqlite3.connect() in py/tag_index.py → T1005 "Data from Local System"

py/tag_index.py maintains a local SQLite cache of the tags inside the user's own tag-group .json files, so the sidebar's deep search — "which of my groups contain this tag" — does not re-read tens of thousands of files on every keystroke. It is written to <tag groups root>/.erenodes_tag_index.db, beside the collection it describes, and can be rebuilt from those files at any time.

The decisive point: the node pack makes no outbound network connections at all.

$ grep -rnE "^\s*(import|from)\s+(urllib|requests|socket|http|httpx|subprocess|ftplib|smtplib|pickle)" py/ __init__.py
$ grep -rnE "\bos\.system\(|\bexec\(|\beval\(|subprocess\.|urlopen\(" py/ __init__.py
$

Both return nothing. The only third-party imports anywhere in py/ are aiohttp.web — used solely to register routes on ComfyUI's own server.PromptServer.instance.routes — plus safetensors and folder_paths. Reading a local cache when no egress path exists cannot be data exfiltration.

3. urllib.request.urlopen and os.environ.get in scripts/animadex_to_tag_groups.py

This file is shipped deliberately and documented in both README.md and scripts/README.md, which opens with:

Standalone command-line tools. Nothing here is loaded by the extension, imported by a node, or reachable from the ComfyUI UI — these are run by hand, with your own Python, when you want them.

That is verifiable rather than a claim: scripts/ is not imported by __init__.py or by anything under py/, contains no __init__.py, and registers no nodes and no routes. Installing the pack never executes it. It is a bulk importer the user runs explicitly:

python animadex_to_tag_groups.py --token YOUR_TOKEN \
    --out ".../models/tag_groups" --dry-run --limit 20

Line 99 performs an HTTP GET against animadex.net, the public character catalogue the tool exists to import from. It is the only host the script contacts, it is hard-coded, and the traffic is inbound data — nothing from the user's machine is uploaded.

Line 202 reads ANIMADEX_IMPORT_TOKEN as the argparse default for --token. That is the user's own export token for that same site, and the environment variable exists so the token stays out of shell history, exactly as the README instructs. Flagging it as environment-variable hijacking inverts what it does: the script reads one specifically-named variable the user set for it, and sends it to the service that issued it.

Together those two lines produce the "collect credentials + exfiltrate" reading. In context they are: read the API token the user gave this tool, call the API it belongs to, write the results into the folder the user named with --out. Standard library only, no dependencies, --dry-run supported.

Note on 3.0.0 – 3.2.0 (banned)

Previous edits to this manual review requests were made based on message from discord security-review channel with was incomplete as it included only the python_network_operations false positives and didn't mention the actual ban reason I just found through API. Those bans (missing is_within() containment check ) were in fact correct and I am not contesting them.

It was fixed in 3.3.0 and as such versions 3.0.0, 3.0.1, 3.1.0 and 3.2.0 have been deprecated in the registry so nobody lands on them.

Originally created by @Erehr on GitHub (Aug 15, 2026). Original GitHub issue: https://github.com/Comfy-Org/ComfyUI-Manager/issues/3169 Node: `comfyui-erenodes` · Repo: https://github.com/Erehr/ComfyUI-EreNodes > [!NOTE] > Versions **3.3.0**, **3.4.0** and **3.5.0** are marked `Flagged`. Every finding is `info` severity and every one is a pattern match with no security meaning. I would like the flags cleared. [https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.3.0](https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.3.0) [https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.4.0](https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.4.0) [https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.5.0](https://registry.comfy.org/admin/nodeversions?nodeId=comfyui-erenodes&version=3.5.0) ## Findings | Version | Finding | Location | | --- | --- | --- | | 3.3.0–3.5.0 | `python_network_operations` | `web/prompt.js`, `web/prompt_autocomplete.js`, `web/js/contextmenu.js` | | 3.4.0, 3.5.0 | database connection → `T1005` *Data from Local System* | `py/tag_index.py` | | 3.4.0, 3.5.0 | network operation → `T1041`/`T1048` *Exfiltration* | `scripts/animadex_to_tag_groups.py` | | 3.4.0, 3.5.0 | environment variable read | `scripts/animadex_to_tag_groups.py` | ## 1. `.connect()` and `.bind()` in `.js` files → `python_network_operations` A **Python** network ruleset is being run against **JavaScript**. - `originNode.connect(...)` is the **LiteGraph** canvas API, re-wiring graph links when a node is converted to another node type. No socket, no URL. - `this.onKeyDown.bind(this)` and `this.close.bind(this)` are the standard idiom for keeping `this` in a DOM event handler. `.connect()` and `.bind()` are two of the most common method names in browser and canvas JavaScript and carry no network meaning there. ## 2. `sqlite3.connect()` in `py/tag_index.py` → T1005 "Data from Local System" `py/tag_index.py` maintains a local SQLite cache of the tags inside the user's own tag-group `.json` files, so the sidebar's deep search — *"which of my groups contain this tag"* — does not re-read tens of thousands of files on every keystroke. It is written to `<tag groups root>/.erenodes_tag_index.db`, beside the collection it describes, and can be rebuilt from those files at any time. The decisive point: **the node pack makes no outbound network connections at all.** ```console $ grep -rnE "^\s*(import|from)\s+(urllib|requests|socket|http|httpx|subprocess|ftplib|smtplib|pickle)" py/ __init__.py $ grep -rnE "\bos\.system\(|\bexec\(|\beval\(|subprocess\.|urlopen\(" py/ __init__.py $ ``` Both return nothing. The only third-party imports anywhere in `py/` are `aiohttp.web` — used solely to register routes on ComfyUI's own `server.PromptServer.instance.routes` — plus `safetensors` and `folder_paths`. Reading a local cache when no egress path exists cannot be data exfiltration. ## 3. `urllib.request.urlopen` and `os.environ.get` in `scripts/animadex_to_tag_groups.py` This file is shipped deliberately and documented in both `README.md` and `scripts/README.md`, which opens with: > Standalone command-line tools. Nothing here is loaded by the extension, imported by a node, or reachable from the ComfyUI UI — these are run by hand, with your own Python, when you want them. That is verifiable rather than a claim: `scripts/` is not imported by `__init__.py` or by anything under `py/`, contains no `__init__.py`, and registers no nodes and no routes. Installing the pack never executes it. It is a bulk importer the user runs explicitly: ```bash python animadex_to_tag_groups.py --token YOUR_TOKEN \ --out ".../models/tag_groups" --dry-run --limit 20 ``` **Line 99** performs an HTTP `GET` against `animadex.net`, the public character catalogue the tool exists to import from. It is the only host the script contacts, it is hard-coded, and the traffic is inbound data — nothing from the user's machine is uploaded. **Line 202** reads `ANIMADEX_IMPORT_TOKEN` as the `argparse` default for `--token`. That is the user's own export token **for that same site**, and the environment variable exists so the token stays out of shell history, exactly as the README instructs. Flagging it as environment-variable hijacking inverts what it does: the script reads one specifically-named variable the user set for it, and sends it to the service that issued it. Together those two lines produce the "collect credentials + exfiltrate" reading. In context they are: read the API token the user gave this tool, call the API it belongs to, write the results into the folder the user named with `--out`. Standard library only, no dependencies, `--dry-run` supported. <details> <summary>Note on 3.0.0 – 3.2.0 (banned)</summary> Previous edits to this manual review requests were made based on message from discord security-review channel with was incomplete as it included only the python_network_operations false positives and didn't mention the actual ban reason I just found through API. Those bans (missing is_within() containment check ) were in fact correct and I am not contesting them. It was fixed in 3.3.0 and as such versions 3.0.0, 3.0.1, 3.1.0 and 3.2.0 have been **deprecated** in the registry so nobody lands on them. </details>
Author
Owner

@Erehr commented on GitHub (Sep 7, 2026):

Update: versions 3.3.0 to 3.5.0 were changed from flagged to banned too.

Version Status Recorded reason
3.6.0 Flagged scanner output only
3.5.0 Banned policy-v0.2: RCE (code execution)
3.4.0 Banned policy-v0.2: RCE (code execution)
3.3.0 Banned policy-v0.2: command injection

Full text on the three bans, set by drltdata@comfy.org:

policy-v0.2: RCE (code execution) - attacker-reachable via unauthenticated /prompt
(node widget) or no-auth route; confirmed by code-level verify-deep.

What I am asking for

The message states the finding was confirmed at code level. Please share the file and line, or a
request that reaches it.
I will fix a real vulnerability the same day. What I cannot do is fix a
finding I cannot locate, and I have not been able to reproduce either claim against my own source.

Why I believe both claims are mistaken

There is no execution primitive in the package to reach. Across py/, scripts/ and
__init__.py there is no subprocess, os.system, os.popen, eval, exec, __import__,
pickle, or shell=True. No shell is ever invoked, so there is nothing for a command injection to
inject into. This is checkable in one grep.

Measured against the published security standards:

Standard Status
No eval / exec Not present anywhere in the package
No subprocess pip install No subprocess at all
No code obfuscation Plain, commented source

The nodes do not touch the filesystem or any execution path. Every process() in
py/prompt.py concatenates strings and returns them. Widget values arriving from /prompt are
joined with a separator and passed on. That is the entire node-side surface, which is what the
"node widget" half of the ban message points at.

Route-by-route containment (the "no-auth route" half)

Every route that touches a path resolves it against a root and checks containment with
os.path.commonpath (is_within, py/paths.py:77) rather than a startswith prefix test, so a
sibling directory cannot pass either:

Route Containment What it can write
GET /erenodes/get_tag_group is_within(prompts_dir) reads only
GET /erenodes/view/{type}/{path} is_within(model or prompts root) reads only, image extension whitelist
POST /erenodes/save_tag_group is_within(prompts_dir) .json only, extension forced
POST /erenodes/save_file_image is_within(model root), target must already exist .webp only, see below
POST /erenodes/delete_file_image is_within(prompts_dir) deletes covers of an existing group
POST /erenodes/create_folder is_within(prompts_dir) directory only
POST /erenodes/rename_path is_within(prompts_dir), root rejected .json extension forced
POST /erenodes/move_path both ends is_within(prompts_dir) moves within the root
POST /erenodes/delete_path is_within(prompts_dir), root rejected deletes within the root
POST /erenodes/extract_prompt ComfyUI's own input dir, sanitized basename image extensions only

Cover images cannot be used to plant a file of a chosen type: py/images.py decodes the upload
through Pillow and re-encodes it as WebP under a name the server builds (f"{basename}.webp"), so
neither the bytes nor the extension are attacker-controlled, and an upload Pillow cannot decode is
rejected.

The two scanner flags are string matches, and both are false

These are the flags recorded in statusHistory for the banned versions:

  • $sqlite1 matched sqlite3.connect( at py/tag_index.py:93, reported as
    python_database_connections with admin_tags: ["any-network-requests"]. It is a local SQLite
    file inside the user's own tag-group folder, used as a search index over their own files. No
    network, no external database.

  • $socket3 matched .connect( at web/prompt.js:257:

    if (originNode) originNode.connect(link.origin_slot, newNode, i);
    

    That is LiteGraph node wiring, in a browser file, reported under an issue type named
    python_network_operations.

The package makes no outbound network requests of any kind. Every fetch() under web/ targets a
relative /erenodes/* or ComfyUI path on the same origin.

What I changed anyway

Re-reading the routes for this reply I found one worth tightening, and have fixed it:
POST /erenodes/set_setting accepted any key and value into the package's own settings.json. It
now accepts only the single key the UI writes (autocomplete.csv), and only values naming a CSV
that already exists in the package's __autocomplete__ folder. It stored JSON data, so it was not
a code-execution path, but it was unauthenticated state mutation and should not have been open.

On the category

If the actual concern is that the package registers unauthenticated /erenodes/* routes that read
and write files under the tag-group and model directories, I would rather meet the requirement than
argue about the label. ComfyUI routes are unauthenticated by default and these operate strictly
inside the folders the feature manages, but if policy-v0.2 expects something specific of custom
routes - a permission model, a documented allowlist, an opt-in setting - point me at it and I will
implement it.

What I would ask either way is that the ban text match the finding. "RCE" and "command injection"
against a package containing no execution primitive read as a far more serious claim than
"unauthenticated file routes", and users see that text.

<!-- gh-comment-id:5566347076 --> @Erehr commented on GitHub (Sep 7, 2026): Update: versions 3.3.0 to 3.5.0 were changed from flagged to banned too. | Version | Status | Recorded reason | | --- | --- | --- | | 3.6.0 | Flagged | scanner output only | | 3.5.0 | **Banned** | `policy-v0.2: RCE (code execution)` | | 3.4.0 | **Banned** | `policy-v0.2: RCE (code execution)` | | 3.3.0 | **Banned** | `policy-v0.2: command injection` | Full text on the three bans, set by `drltdata@comfy.org`: ``` policy-v0.2: RCE (code execution) - attacker-reachable via unauthenticated /prompt (node widget) or no-auth route; confirmed by code-level verify-deep. ``` ### What I am asking for The message states the finding was confirmed at code level. **Please share the file and line, or a request that reaches it.** I will fix a real vulnerability the same day. What I cannot do is fix a finding I cannot locate, and I have not been able to reproduce either claim against my own source. ### Why I believe both claims are mistaken **There is no execution primitive in the package to reach.** Across `py/`, `scripts/` and `__init__.py` there is no `subprocess`, `os.system`, `os.popen`, `eval`, `exec`, `__import__`, `pickle`, or `shell=True`. No shell is ever invoked, so there is nothing for a command injection to inject into. This is checkable in one grep. Measured against [the published security standards](https://docs.comfy.org/registry/standards): | Standard | Status | | --- | --- | | No `eval` / `exec` | Not present anywhere in the package | | No `subprocess` pip install | No `subprocess` at all | | No code obfuscation | Plain, commented source | **The nodes do not touch the filesystem or any execution path.** Every `process()` in `py/prompt.py` concatenates strings and returns them. Widget values arriving from `/prompt` are joined with a separator and passed on. That is the entire node-side surface, which is what the "node widget" half of the ban message points at. <details> <summary><b>Route-by-route containment (the "no-auth route" half)</b></summary> Every route that touches a path resolves it against a root and checks containment with `os.path.commonpath` (`is_within`, `py/paths.py:77`) rather than a `startswith` prefix test, so a sibling directory cannot pass either: | Route | Containment | What it can write | | --- | --- | --- | | `GET /erenodes/get_tag_group` | `is_within(prompts_dir)` | reads only | | `GET /erenodes/view/{type}/{path}` | `is_within(model or prompts root)` | reads only, image extension whitelist | | `POST /erenodes/save_tag_group` | `is_within(prompts_dir)` | `.json` only, extension forced | | `POST /erenodes/save_file_image` | `is_within(model root)`, target must already exist | `.webp` only, see below | | `POST /erenodes/delete_file_image` | `is_within(prompts_dir)` | deletes covers of an existing group | | `POST /erenodes/create_folder` | `is_within(prompts_dir)` | directory only | | `POST /erenodes/rename_path` | `is_within(prompts_dir)`, root rejected | `.json` extension forced | | `POST /erenodes/move_path` | both ends `is_within(prompts_dir)` | moves within the root | | `POST /erenodes/delete_path` | `is_within(prompts_dir)`, root rejected | deletes within the root | | `POST /erenodes/extract_prompt` | ComfyUI's own input dir, sanitized basename | image extensions only | Cover images cannot be used to plant a file of a chosen type: `py/images.py` decodes the upload through Pillow and re-encodes it as WebP under a name the server builds (`f"{basename}.webp"`), so neither the bytes nor the extension are attacker-controlled, and an upload Pillow cannot decode is rejected. </details> <details> <summary><b>The two scanner flags are string matches, and both are false</b></summary> These are the flags recorded in `statusHistory` for the banned versions: * `$sqlite1` matched `sqlite3.connect(` at `py/tag_index.py:93`, reported as `python_database_connections` with `admin_tags: ["any-network-requests"]`. It is a local SQLite file inside the user's own tag-group folder, used as a search index over their own files. No network, no external database. * `$socket3` matched `.connect(` at `web/prompt.js:257`: ```js if (originNode) originNode.connect(link.origin_slot, newNode, i); ``` That is LiteGraph node wiring, in a browser file, reported under an issue type named `python_network_operations`. The package makes no outbound network requests of any kind. Every `fetch()` under `web/` targets a relative `/erenodes/*` or ComfyUI path on the same origin. </details> ### What I changed anyway Re-reading the routes for this reply I found one worth tightening, and have fixed it: `POST /erenodes/set_setting` accepted any key and value into the package's own `settings.json`. It now accepts only the single key the UI writes (`autocomplete.csv`), and only values naming a CSV that already exists in the package's `__autocomplete__` folder. It stored JSON data, so it was not a code-execution path, but it was unauthenticated state mutation and should not have been open. ### On the category If the actual concern is that the package registers unauthenticated `/erenodes/*` routes that read and write files under the tag-group and model directories, I would rather meet the requirement than argue about the label. ComfyUI routes are unauthenticated by default and these operate strictly inside the folders the feature manages, but if `policy-v0.2` expects something specific of custom routes - a permission model, a documented allowlist, an opt-in setting - point me at it and I will implement it. What I would ask either way is that the ban text match the finding. "RCE" and "command injection" against a package containing no execution primitive read as a far more serious claim than "unauthenticated file routes", and users see that text.
Author
Owner

@Erehr commented on GitHub (Sep 7, 2026):

@ltdrdata sorry to tag you directly - this has sat three weeks and the situation has since changed
from flagged to banned, so I would rather it reach someone than keep aging.

I audited the pack against #3118 rather than against the ban wording, since that thread shows
what this class actually means in practice. Two things came out of it, both shipped in 3.6.2:

  • is_within resolved with abspath, so a symlink inside the tag-group folder would have passed
    containment while pointing outside it. Now realpath on both sides, the pattern you asked
    pixaroma for. Traversal, absolute-join base-drop, sibling-prefix and UNC were already refused;
    the symlink case was a real gap and I would not have looked for it without that review.
  • POST /erenodes/set_setting accepted any key and value into the pack's own settings.json. Now
    restricted to the one key the UI writes, with a value that must name an existing CSV in the
    pack's __autocomplete__ folder.

Neither is code execution and I am not claiming either is the finding behind the ban - reporting
them because I went looking properly and that is what turned up.

What I still cannot find is the RCE or the command injection. There is no subprocess,
os.system, os.popen, eval, exec, __import__, pickle, shell=True, os.startfile or
xdg-open anywhere in py/, scripts/ or __init__.py - no shell is invoked, so there is nothing
to inject into. On the /prompt path specifically, every process() joins widget strings and
returns them; the node classes never touch the filesystem, so the widget-to-disk route does not
exist here. Full route table and per-file detail in the report above.

On the original subject of this issue, the three python_network_operations hits are still
.connect( and .bind( in .js files.
registry-backend#223 reports the same
Python-rules-against-JavaScript mismatch at much larger scale (56 of 75 findings), as do #214, #215,
#216 and #220 there, so it looks like one scanner bug rather than several packages.

If you can point me at the file and line behind the ban, or a request that reaches it, I will fix it
the same day. If the concern is the category rather than a site - unauthenticated custom routes
doing contained file I/O - tell me the expected pattern and I will build to it.

<!-- gh-comment-id:5566958245 --> @Erehr commented on GitHub (Sep 7, 2026): @ltdrdata sorry to tag you directly - this has sat three weeks and the situation has since changed from flagged to banned, so I would rather it reach someone than keep aging. **I audited the pack against #3118 rather than against the ban wording**, since that thread shows what this class actually means in practice. Two things came out of it, both shipped in **3.6.2**: - `is_within` resolved with `abspath`, so a symlink inside the tag-group folder would have passed containment while pointing outside it. Now `realpath` on both sides, the pattern you asked pixaroma for. Traversal, absolute-join base-drop, sibling-prefix and UNC were already refused; the symlink case was a real gap and I would not have looked for it without that review. - `POST /erenodes/set_setting` accepted any key and value into the pack's own `settings.json`. Now restricted to the one key the UI writes, with a value that must name an existing CSV in the pack's `__autocomplete__` folder. Neither is code execution and I am not claiming either is the finding behind the ban - reporting them because I went looking properly and that is what turned up. **What I still cannot find is the RCE or the command injection.** There is no `subprocess`, `os.system`, `os.popen`, `eval`, `exec`, `__import__`, `pickle`, `shell=True`, `os.startfile` or `xdg-open` anywhere in `py/`, `scripts/` or `__init__.py` - no shell is invoked, so there is nothing to inject into. On the `/prompt` path specifically, every `process()` joins widget strings and returns them; the node classes never touch the filesystem, so the widget-to-disk route does not exist here. Full route table and per-file detail in the report above. **On the original subject of this issue**, the three `python_network_operations` hits are still `.connect(` and `.bind(` in `.js` files. [registry-backend#223](https://github.com/Comfy-Org/registry-backend/issues/223) reports the same Python-rules-against-JavaScript mismatch at much larger scale (56 of 75 findings), as do #214, #215, #216 and #220 there, so it looks like one scanner bug rather than several packages. If you can point me at the file and line behind the ban, or a request that reaches it, I will fix it the same day. If the concern is the category rather than a site - unauthenticated custom routes doing contained file I/O - tell me the expected pattern and I will build to it.
Author
Owner

@ltdrdata commented on GitHub (Sep 13, 2026):

Hi @Erehr, thanks for the detailed write-up — but there's a conflation here that's worth clearing up, because it changes the conclusion.

The automated findings you're contesting (the network / DB / env-var items, all info-severity) are not the ban reason. Those are only the flagging condition that triggers a manual review — they don't, by themselves, ban anything, and on their own they're low-signal as you say.

The ban was a separate review decision, on a genuine higher-severity issue in the 3.4.0–3.6.0 line: an unauthenticated arbitrary file read (path traversal) reachable through the settings route — the same class your own 3.6.1 change fixed when you added the ALLOWED_SETTINGS key check on set_setting plus CSV-value validation. Before that hardening, the setting that selects the autocomplete CSV was attacker-settable to an out-of-tree path and then read back unguarded, with no authentication on the route. That is what the review acted on — not the info-severity findings cited.

Because that fix landed in 3.6.1, the registry already reflects the right outcome:

  • 3.6.1 / 3.6.2 / 3.6.3 are Active — current users are unaffected, and an independent deep re-verification of 3.6.3 confirms it's clean.
  • 3.4.0 / 3.5.0 / 3.6.0 remain Banned by design, as they predate the fix and carry the unauthenticated read.
  • 3.3.0 isn't a current registry version, so there's nothing to change there.

Net: nothing to clear on 3.4.0–3.6.0, and nothing you need to do — publishing from 3.6.1 onward is already the resolution. Thanks again for the fix.

<!-- gh-comment-id:5653765981 --> @ltdrdata commented on GitHub (Sep 13, 2026): Hi @Erehr, thanks for the detailed write-up — but there's a conflation here that's worth clearing up, because it changes the conclusion. The automated findings you're contesting (the network / DB / env-var items, all info-severity) are **not** the ban reason. Those are only the *flagging condition* that triggers a manual review — they don't, by themselves, ban anything, and on their own they're low-signal as you say. The ban was a separate *review decision*, on a genuine higher-severity issue in the 3.4.0–3.6.0 line: an **unauthenticated arbitrary file read (path traversal)** reachable through the settings route — the same class your own 3.6.1 change fixed when you added the `ALLOWED_SETTINGS` key check on `set_setting` plus CSV-value validation. Before that hardening, the setting that selects the autocomplete CSV was attacker-settable to an out-of-tree path and then read back unguarded, with no authentication on the route. That is what the review acted on — not the info-severity findings cited. Because that fix landed in 3.6.1, the registry already reflects the right outcome: - **3.6.1 / 3.6.2 / 3.6.3 are Active** — current users are unaffected, and an independent deep re-verification of 3.6.3 confirms it's clean. - **3.4.0 / 3.5.0 / 3.6.0 remain Banned by design**, as they predate the fix and carry the unauthenticated read. - **3.3.0** isn't a current registry version, so there's nothing to change there. Net: nothing to clear on 3.4.0–3.6.0, and nothing you need to do — publishing from 3.6.1 onward is already the resolution. Thanks again for the fix.
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#1114
No description provided.