Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions folder_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from typing import Literal, List
from collections.abc import Collection

import json
from comfy.cli_args import args

supported_pt_extensions: set[str] = {'.ckpt', '.pt', '.pt2', '.bin', '.pth', '.safetensors', '.pkl', '.sft'}
Expand All @@ -13,11 +13,38 @@

# --base-directory - Resets all default paths configured in folder_paths with a new base path
if args.base_directory:
base_path = os.path.abspath(args.base_directory)
raw_path = os.path.abspath(args.base_directory)
else:
base_path = os.path.dirname(os.path.realpath(__file__))
raw_path = os.path.dirname(os.path.realpath(__file__))


def valid_path(saved_path,description = "Instance Folder"):
if os.path.exists(saved_path):
return saved_path

redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
if os.path.exists(redirect_path):
with open(redirect_path,"r") as f:
redirects = json.load(f)
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
Comment on lines +31 to +32

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Avoid prompting from module import.

valid_path() is called while folder_paths.py imports, so a missing base/model/output directory can block indefinitely or raise EOFError in headless startup. Route relocation through an explicit validation/recovery step, or fail with a clear exception instead of calling input() here.

Also applies to: 46-48, 91-91

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` around lines 31 - 32, Module import should not block on
interactive path recovery in valid_path(). Move the relocation flow out of
folder_paths.py import-time logic so valid_path(), and the callers for
base/model/output paths, do not call input() during import; instead use an
explicit recovery/validation step or raise a clear exception when a path is
missing. Update the logic around valid_path and any related path initialization
helpers so they fail fast or are invoked only from an interactive entrypoint.

redirects = {}
if os.path.exists(redirect_path):
with open(redirect_path, "r") as f:
redirects = json.load(f)
redirects[description] = new_path
with open(redirect_path, "w") as f:
json.dump(redirects, f, indent=4)

return new_path
Comment on lines +29 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate redirected and entered paths before returning them.

Both stored redirects and new_path are returned without enforcing absolute path, existence, or directory-ness. That can leave base_path, models_dir, or output_directory pointing at an empty/relative/nonexistent path after the “recovery” flow.

Proposed guard
-            if description in redirects and os.path.exists(redirects[description]):
-                return redirects[description]
+            redirected_path = redirects.get(description)
+            if redirected_path and os.path.isabs(redirected_path) and os.path.isdir(redirected_path):
+                return redirected_path
...
-    new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()        
+    new_path = input(f"Please paste the updated absolute path for '{description}': ").strip()
+    if not os.path.isabs(new_path) or not os.path.isdir(new_path):
+        raise FileNotFoundError(f"{description} must be an existing absolute directory: {new_path}")

As per coding guidelines, unsupported paths and bad states should fail with clear errors instead of silently producing worse behavior.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
try:
redirects = {}
if os.path.exists(redirects):
with open(redirects, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass
return new_path
redirected_path = redirects.get(description)
if redirected_path and os.path.isabs(redirected_path) and os.path.isdir(redirected_path):
return redirected_path
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path = input(f"Please paste the updated absolute path for '{description}': ").strip()
if not os.path.isabs(new_path) or not os.path.isdir(new_path):
raise FileNotFoundError(f"{description} must be an existing absolute directory: {new_path}")
try:
redirects = {}
if os.path.exists(redirects):
with open(redirects, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass
return new_path
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 35-35: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "r")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)


[warning] 37-37: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "w")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` around lines 29 - 42, The path recovery logic in
folder_paths should validate both the stored redirect and the user-entered
new_path before returning them. Update the redirect lookup/entry flow to ensure
the resolved path is absolute, exists, and is a directory before assigning it
for base_path, models_dir, or output_directory, and raise a clear error instead
of silently returning an invalid path. Use the existing redirect handling block
and new_path prompt flow to locate the fix.

Source: Coding guidelines




base_path = valid_path(raw_path,description = "ComfyUI Core Directory")

models_dir = os.path.join(base_path, "models")
models_dir =valid_path( os.path.join(base_path,"models"),description = "Model Directory")
folder_names_and_paths["checkpoints"] = ([os.path.join(models_dir, "checkpoints")], supported_pt_extensions)
folder_names_and_paths["configs"] = ([os.path.join(models_dir, "configs")], [".yaml"])

Expand Down Expand Up @@ -60,7 +87,7 @@

folder_names_and_paths["detection"] = ([os.path.join(models_dir, "detection")], supported_pt_extensions)

output_directory = os.path.join(base_path, "output")
output_directory =valid_path( os.path.join(base_path, "output"),"Output Directory")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Don’t require the default output directory to pre-exist.

output_directory is a writable destination; prompting when <base>/output is missing breaks fresh or relocated instances where the directory can be created. Keep validation for relocated existing roots, but create or tolerate the default output directory before downstream callers use it.

Proposed adjustment
-output_directory =valid_path( os.path.join(base_path, "output"),"Output Directory")
+output_directory = os.path.join(base_path, "output")
+os.makedirs(output_directory, exist_ok=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
output_directory =valid_path( os.path.join(base_path, "output"),"Output Directory")
output_directory = os.path.join(base_path, "output")
os.makedirs(output_directory, exist_ok=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` at line 91, The default output path in folder_paths.py is
being treated as if it must already exist, which blocks fresh setups. Update the
output_directory initialization around valid_path(os.path.join(base_path,
"output"), "Output Directory") so the default <base>/output is created or
accepted when missing, while still keeping validation behavior for relocated
existing roots. Use the existing output_directory and valid_path flow to ensure
downstream callers always get a writable destination without prompting for the
default case.

temp_directory = os.path.join(base_path, "temp")
input_directory = os.path.join(base_path, "input")
user_directory = os.path.join(base_path, "user")
Expand Down