{"record":{"id":"d71356ecac1ffc7e","repo":"unslothai/unsloth","slug":"dataset-path-may-not-contain-segments-raw-r","errorCode":null,"errorMessage":"dataset path may not contain '..' segments: {raw!r}","messagePattern":"dataset path may not contain '\\.\\.' segments: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"studio/backend/hub/utils/paths.py","lineNumber":399,"sourceCode":"    \"\"\"\n    try:\n        path_real = os.path.normcase(os.path.realpath(str(path)))\n        root_real = os.path.normcase(os.path.realpath(str(root)))\n        return os.path.commonpath([path_real, root_real]) == root_real\n    except (OSError, ValueError):\n        return False\n\n\ndef resolve_dataset_path(path_value: str) -> Path:\n    raw = str(path_value or \"\").strip()\n    if \"\\x00\" in raw:\n        raise ValueError(\"dataset path may not contain null bytes\")\n    # Normalize first so Windows/UNC and backslash paths resolve like the rest of the Hub path\n    # layer, and a backslashed '..' is caught by the traversal guard below.\n    normalized = normalize_path(raw)\n    path = Path(normalized).expanduser()\n    if \"..\" in path.parts:\n        raise ValueError(f\"dataset path may not contain '..' segments: {raw!r}\")\n    if path.is_absolute():\n        for root in (datasets_root(), dataset_uploads_root(), recipe_datasets_root()):\n            try:\n                _assert_contained(path, root)\n                return path\n            except ValueError:\n                continue\n        raise ValueError(f\"dataset path must be relative or under a dataset root: {raw!r}\")\n\n    parts = [part for part in Path(normalized).parts if part not in (\"\", \".\")]\n    if parts[:2] == [\"assets\", \"datasets\"]:\n        parts = parts[2:]\n    if parts and parts[0] == \"uploads\":\n        cleaned = Path(*parts[1:]) if len(parts) > 1 else Path()\n        return dataset_uploads_root() / cleaned\n    if parts and parts[0] == \"recipes\":\n        cleaned = Path(*parts[1:]) if len(parts) > 1 else Path()\n        return recipe_datasets_root() / cleaned","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/hub/utils/paths.py#L381-L417","documentation":"Traversal guard in resolve_dataset_path: after normalize_path (which converts backslashes so Windows-style '..\\' can't slip through) and expanduser, the Path's parts still contain a '..' segment. '..' would let a relative dataset path escape its intended root when joined, so any occurrence is rejected outright — resolution to a root happens only after this check.","triggerScenarios":"Passing 'assets/datasets/../../secrets.txt', 'uploads/../config', or '..\\..\\windows\\system32' to a dataset path resolution API; a UI file picker that returns relative paths with parent segments.","commonSituations":"Path-traversal attempts (../../../../etc/passwd); legitimate users trying to reference a sibling directory ('../shared/data.csv'); symlinks are fine but literal '..' text is not.","solutions":["Reference the target by its own path under the dataset root, without '..' — e.g. 'shared/data.csv' if that is its logical location.","If the caller has an arbitrary user path, resolve it to an absolute path first and check containment against the dataset root instead of embedding '..'.","Escape/normalize user input client-side and reject '..' segments before submission."],"exampleFix":"# before\nresolve_dataset_path('uploads/../../etc/passwd')\n# after\nresolve_dataset_path('uploads/mydata.csv')   # stay inside the dataset root","handlingStrategy":"validation","validationCode":"def has_dotdot(path_value: str) -> bool:\n    return \"..\" in Path((path_value or \"\").strip().replace(\"\\\\\", \"/\")).parts","typeGuard":null,"tryCatchPattern":"try:\n    p = resolve_dataset_path(value)\nexcept ValueError as e:\n    if \"'..'\" in str(e):\n        return bad_request(\"dataset path must not contain '..' — use a path under the dataset root\")","preventionTips":["Normalize separators before inspecting parts — backslash '..\\\\' is converted by the API, do the same client-side.","Map user-chosen files to logical dataset-relative paths instead of passing raw OS paths.","Remember literal '..' text is rejected even if it would resolve somewhere safe."],"tags":["validation","security","path-traversal","datasets"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}