{"record":{"id":"61a6653bb9924b6d","repo":"Comfy-Org/ComfyUI","slug":"invalid-folder-name-folder-name-r-resolves-outs","errorCode":null,"errorMessage":"Invalid folder name {folder_name!r}: resolves outside of {base_dir}","messagePattern":"Invalid folder name (.+?): resolves outside of (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_extras/nodes_dataset.py","lineNumber":54,"sourceCode":"        if img.mode == \"I\":\n            img = img.point(lambda i: i * (1 / 255))\n        img = img.convert(\"RGB\")\n        img_array = np.array(img).astype(np.float32) / 255.0\n        img_tensor = torch.from_numpy(img_array)[None,]\n        output_images.append(img_tensor)\n\n    return output_images\n\n\ndef secure_subfolder_path(base_dir, folder_name):\n    \"\"\"Resolve folder_name inside base_dir, rejecting anything that escapes it.\n\n    Blocks '..', absolute paths, drive letters and symlink escapes using the\n    same realpath containment check as the core file endpoints.\n    \"\"\"\n    target = os.path.abspath(os.path.join(base_dir, folder_name))\n    if not folder_paths.is_within_directory(base_dir, target):\n        raise ValueError(f\"Invalid folder name {folder_name!r}: resolves outside of {base_dir}\")\n    return target\n\n\ndef list_dataset_folders():\n    \"\"\"Relative paths of dataset folders found under all dataset roots.\n\n    Any subfolder containing a metadata.json or *.safetensors shard counts as\n    a dataset; the walk doesn't descend into matched folders.\n\n    Symlinked directories are followed, but symlink loops are avoided.\n    \"\"\"\n    found = set()\n\n    for root in folder_paths.get_folder_paths(\"datasets\"):\n        if not os.path.isdir(root):\n            continue\n\n        root = os.path.abspath(root)","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_extras/nodes_dataset.py#L36-L72","documentation":"secure_subfolder_path joins folder_name onto base_dir, resolves it to an absolute path, and uses folder_paths.is_within_directory to guarantee the result stays inside base_dir. Any folder_name that escapes — '..' segments, absolute paths, Windows drive letters, or symlinked escapes — raises this ValueError. It is the containment guard that stops dataset node inputs from touching arbitrary filesystem paths.","triggerScenarios":"Passing folder_name like '../..', '/etc', 'C:\\\\other', or a path whose resolved symlink target lies outside the datasets root. Also crafted names like 'safe/../../outside' that normalize outside the root.","commonSituations":"Users pasting absolute paths into a field that expects a relative subfolder; prompt-injection via untrusted combo strings; symlinked dataset folders whose target moved outside the root.","solutions":["Use a plain relative subfolder name such as 'my_dataset' or 'sets/train_a'.","Remove any leading '/', drive letters, or '..' components from the input.","If a symlinked dataset legitimately lives outside the root, add its parent as an extra datasets folder in extra_model_paths.yaml instead of symlinking past the guard."],"exampleFix":"# before\nfolder_name = \"/data/my_dataset\"\n# after\nfolder_name = \"my_dataset\"","handlingStrategy":"validation","validationCode":"import re\nSAFE_NAME = re.compile(r\"^[^/\\\\]+(?:[/\\\\][^/\\\\]+)*$\")\ndef safe_folder_name(name: str) -> bool:\n    return bool(name) and name not in (\".\", \"..\") and \"..\" not in name.split(\"/\" + \"/\") and SAFE_NAME.match(name) is not None","typeGuard":"def is_relative_subfolder(name) -> bool:\n    return (isinstance(name, str) and name.strip() != \"\" and not os.path.isabs(name)\n            and \"..\" not in name.replace(\"\\\\\", \"/\").split(\"/\"))","tryCatchPattern":null,"preventionTips":["Only pass relative subfolder names; never absolute paths.","Treat any folder_name from untrusted prompts as hostile and regex-validate it.","Register out-of-tree datasets as extra roots instead of symlinking past the guard."],"tags":["security","path-traversal","dataset","comfyui"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}