{"record":{"id":"7e3b3b1c4ab42ee2","repo":"unslothai/unsloth","slug":"save-directory-may-not-contain-segments","errorCode":null,"errorMessage":"save_directory may not contain '..' segments","messagePattern":"save_directory may not contain '\\.\\.' segments","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/models/export.py","lineNumber":32,"sourceCode":"    if value is None:\n        raise ValueError(\"save_directory is required\")\n    raw = str(value).strip()\n    if not raw:\n        raise ValueError(\"save_directory must not be empty\")\n    if \"\\x00\" in raw:\n        raise ValueError(\"save_directory may not contain null bytes\")\n    if any(ch in raw for ch in (\"\\r\", \"\\n\")):\n        raise ValueError(\"save_directory may not contain control characters\")\n    path = Path(raw).expanduser()\n    path_parts = (*path.parts, *PureWindowsPath(raw).parts, *raw.replace(\"\\\\\", \"/\").split(\"/\"))\n    if any(len(part) > 255 for part in path_parts if part not in (\"\", \".\", \"/\", \"\\\\\")):\n        raise ValueError(\"save_directory path components must be <= 255 characters\")\n    if (\n        \"..\" in path.parts\n        or \"..\" in PureWindowsPath(raw).parts\n        or \"..\" in raw.replace(\"\\\\\", \"/\").split(\"/\")\n    ):\n        raise ValueError(\"save_directory may not contain '..' segments\")\n    return raw\n\n\nclass LoadCheckpointRequest(BaseModel):\n    \"\"\"Request for loading a checkpoint into the export backend.\"\"\"\n\n    checkpoint_path: str = Field(..., description = \"Path to the checkpoint directory\")\n    max_seq_length: int = Field(\n        2048,\n        ge = 128,\n        le = 32768,\n        description = \"Maximum sequence length for loading the model\",\n    )\n    load_in_4bit: bool = Field(\n        True,\n        description = \"Whether to load the model in 4-bit quantization\",\n    )\n    trust_remote_code: bool = Field(","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/models/export.py#L14-L50","documentation":"ValueError from _validate_save_directory when the path contains '..' segments in any interpretation — POSIX parts, Windows PureWindowsPath parts, or naive backslash/slash splitting. This blocks directory traversal: export destinations must be explicit paths, not relative escapes, and the redundant multi-view check closes Windows/POSIX mismatch loopholes (e.g. '..\\..\\evil' on a Linux server that later ships the path to Windows).","triggerScenarios":"Sending save_directory like '../../etc', 'outputs/../../home/user/.ssh', or '..\\..\\C:\\Windows' — accidental relative-path joining in clients, or deliberate traversal attempts against the export endpoint.","commonSituations":"Clients that join a user-supplied relative path onto a base directory without normalizing; security testing; path fields sourced from unvalidated URL parameters.","solutions":["Send an explicit destination path without '..' — resolve relative paths client-side first (os.path.abspath / path.resolve()) before including them in the payload.","In the client, reject any user input containing '..' components for destination fields.","If a traversal attempt shows up in server logs, treat it as a security signal and audit the calling client."],"exampleFix":"# before\npayload = {\"save_directory\": \"../../shared/exports\"}\n# after\npayload = {\"save_directory\": str((BASE_DIR / \"exports\" / name).resolve())}","handlingStrategy":"validation","validationCode":"def save_directory_no_traversal(payload: dict) -> bool:\n    v = payload.get(\"save_directory\")\n    if not isinstance(v, str):\n        return False\n    parts = v.replace(\"\\\\\", \"/\").split(\"/\")\n    return \"..\" not in parts","typeGuard":"def is_traversal_free_path(v: str) -> bool:\n    return \"..\" not in v.replace(\"\\\\\", \"/\").split(\"/\")","tryCatchPattern":null,"preventionTips":["Resolve paths client-side (os.path.abspath / Path.resolve()) before sending.","Reject any '..' in user-supplied destination fields at the UI layer.","Audit server logs for this message — occurrences indicate probing or a client joining relative paths unsafely."],"tags":["validation","security","path-traversal","export","http-422"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}