CVE-2024-32023 (published 2024-04-16T15:15Z)

Kohya_ss is a GUI for Kohya's Stable Diffusion trainers. Kohya_ss is vulnerable to a path injection in the `common_gui.py` `find_and_replace` function. This vulnerability is fixed in 23.1.5.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/bmaltais/kohya_ss
commit_details: repo_url: https://github.com/bmaltais/kohya_ss
author: bmaltais
author_date: 2024-04-11 08:32:17-04:00
msg: Find replace (#2258)

* Improve security to limit finding and replacing contents of any files on the system, that the attacker knows the contents of by specifying the list of acceptable extensions for captions.

* Update caption extension fields to Dropdown with restricted choices for security reasons
repository: repo_url: https://github.com/bmaltais/kohya_ss
repo_name: bmaltais/kohya_ss
repo_language: Python
owner: bmaltais
file_changes: filename: basic_caption_gui.py
change_type: ModificationType.MODIFY
diff: @@ -190,9 +190,9 @@ def gradio_basic_caption_gui_tab(headless=False, default_images_dir=None):
                 show_progress=False,
             )
             # Textbox for caption file extension
-            caption_ext = gr.Textbox(
+            caption_ext = gr.Dropdown(
                 label="Caption file extension",
-                placeholder="Extension for caption file (e.g., .caption, .txt)",
+                choices=[".cap", ".caption", ".txt"],
                 value=".txt",
                 interactive=True,
             )

programming_language: Python
filename: blip_caption_gui.py
change_type: ModificationType.MODIFY
diff: @@ -142,9 +142,9 @@ def gradio_blip_caption_gui_tab(headless=False, default_train_dir=None):
                 show_progress=False,
             )
         with gr.Row():
-            caption_file_ext = gr.Textbox(
+            caption_file_ext = gr.Dropdown(
                 label="Caption file extension",
-                placeholder="Extension for caption file (e.g., .caption, .txt)",
+                choices=[".cap", ".caption", ".txt"],
                 value=".txt",
                 interactive=True,
             )

programming_language: Python
filename: class_basic_training.py
change_type: ModificationType.MODIFY
diff: @@ -98,10 +98,11 @@ class BasicTraining:
                 label="Save every N epochs", value=self.config.get("basic.save_every_n_epochs", 1), precision=0
             )
             # Initialize the caption extension input
-            self.caption_extension = gr.Textbox(
-                label="Caption Extension",
-                placeholder="(Optional) default: .caption",
-                value=self.config.get("basic.caption_extension", ""),
+            self.caption_extension = gr.Dropdown(
+                label="Caption file extension",
+                choices=[".cap", ".caption", ".txt"],
+                value=".txt",
+                interactive=True,
             )
 
     def init_precision_and_resources_controls(self) -> None:

programming_language: Python
filename: common_gui.py
change_type: ModificationType.MODIFY
diff: @@ -715,7 +715,6 @@ def has_ext_files(folder_path: str, file_extension: str) -> bool:
     # If no file with the specified extension is found, return False
     return False
 
-
 def find_replace(
     folder_path: str = "",
     caption_file_ext: str = ".caption",
@@ -747,21 +746,41 @@ def find_replace(
         )
         # Exit the function early
         return
+    
+    # Check if the caption file extension is one of the supported extensions
+    if caption_file_ext not in [".caption", ".txt", ".txt2", ".cap"]:
+        log.error(
+            f"Unsupported file extension {caption_file_ext} for caption files. Please use .caption, .txt, .txt2, or .cap."
+        )
+        # Exit the function early
+        return
+    
+    # Check if the folder path exists
+    if not os.path.exists(folder_path):
+        log.error(f"The provided path '{folder_path}' is not a valid folder.")
+        return
 
     # List all caption files in the folder
-    caption_files = [f for f in os.listdir(folder_path) if f.endswith(caption_file_ext)]
+    try:
+        caption_files = [f for f in os.listdir(folder_path) if f.endswith(caption_file_ext)]
+    except Exception as e:
+        log.error(f"Error accessing folder {folder_path}: {e}")
+        return
 
     # Iterate over the list of caption files
     for caption_file in caption_files:
         # Construct the full path for each caption file
         file_path = os.path.join(folder_path, caption_file)
         # Read and replace text
-        with open(file_path, "r", errors="ignore") as f:
-            content = f.read().replace(search_text, replace_text)
-
-        # Write the updated content back to the file
-        with open(file_path, "w") as f:
-            f.write(content)
+        try:
+            with open(file_path, "r", errors="ignore") as f:
+                content = f.read().replace(search_text, replace_text)
+
+            # Write the updated content back to the file
+            with open(file_path, "w") as f:
+                f.write(content)
+        except Exception as e:
+            log.error(f"Error processing file {file_path}: {e}")
 
 
 def color_aug_changed(color_aug):

programming_language: Python
filename: git_caption_gui.py
change_type: ModificationType.MODIFY
diff: @@ -114,9 +114,9 @@ def gradio_git_caption_gui_tab(headless=False, default_train_dir=None):
                 show_progress=False,
             )
         with gr.Row():
-            caption_ext = gr.Textbox(
+            caption_ext = gr.Dropdown(
                 label="Caption file extension",
-                placeholder="Extension for caption file (e.g., .caption, .txt)",
+                choices=[".cap", ".caption", ".txt"],
                 value=".txt",
                 interactive=True,
             )

programming_language: Python
filename: group_images_gui.py
change_type: ModificationType.MODIFY
diff: @@ -171,9 +171,9 @@ def gradio_group_images_gui_tab(headless=False):
                 info="Generate caption files for the grouped images based on their folder name",
             )
 
-            caption_ext = gr.Textbox(
-                label="Caption Extension",
-                placeholder="Caption file extension (e.g., .txt)",
+            caption_ext = gr.Dropdown(
+                label="Caption file extension",
+                choices=[".cap", ".caption", ".txt"],
                 value=".txt",
                 interactive=True,
             )

programming_language: Python
filename: manual_caption_gui.py
change_type: ModificationType.MODIFY
diff: @@ -298,9 +298,9 @@ def gradio_manual_caption_gui_tab(headless=False, default_images_dir=None):
                 show_progress=False,
             )
             load_images_button = gr.Button("Load", elem_id="open_folder")
-            caption_ext = gr.Textbox(
+            caption_ext = gr.Dropdown(
                 label="Caption file extension",
-                placeholder="Extension for caption file (e.g., .caption, .txt)",
+                choices=[".cap", ".caption", ".txt"],
                 value=".txt",
                 interactive=True,
             )

programming_language: Python
filename: wd14_caption_gui.py
change_type: ModificationType.MODIFY
diff: @@ -188,10 +188,10 @@ def gradio_wd14_caption_gui_tab(
 
         with gr.Row():
 
-            caption_extension = gr.Textbox(
+            caption_extension = gr.Dropdown(
                 label="Caption file extension",
-                placeholder="Extension for caption file (e.g., .caption, .txt)",
-                value=config.get("wd14_caption.caption_extension", ".txt"),
+                choices=[".cap", ".caption", ".txt"],
+                value=".txt",
                 interactive=True,
             )
 

programming_language: Python