{"record":{"id":"f0522cc0375f0511","repo":"unslothai/unsloth","slug":"invalid-path-in-the-pinned-spec-name-source-arch","errorCode":null,"errorMessage":"Invalid path in the pinned {spec.name} source archive","messagePattern":"Invalid path in the pinned (.+?) source archive","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"studio/backend/utils/third_party_source.py","lineNumber":610,"sourceCode":"                    handle.write(chunk)\n    except RuntimeError:\n        raise\n    except (OSError, urllib.error.URLError) as error:\n        raise RuntimeError(f\"Could not download the pinned {spec.name} source archive\") from error\n\n\ndef _archive_member_parts(member: tarfile.TarInfo, spec: PinnedSource) -> tuple[str, ...]:\n    name = member.name[:-1] if member.isdir() and member.name.endswith(\"/\") else member.name\n    parts = tuple(name.split(\"/\"))\n    if (\n        not name\n        or name.startswith(\"/\")\n        or \"\\\\\" in name\n        or any(part in (\"\", \".\", \"..\") for part in parts)\n        or any(PureWindowsPath(part).drive for part in parts)\n        or parts[0] != _archive_root_name(spec)\n    ):\n        raise RuntimeError(f\"Invalid path in the pinned {spec.name} source archive\")\n    return parts\n\n\nclass _BoundedArchiveReader:\n    def __init__(self, handle, limit: int):\n        self._handle = handle\n        self._limit = limit\n        self._read = 0\n\n    def read(self, size: int = -1) -> bytes:\n        remaining = self._limit - self._read\n        requested = remaining + 1 if size < 0 else min(size, remaining + 1)\n        data = self._handle.read(requested)\n        self._read += len(data)\n        if self._read > self._limit:\n            raise RuntimeError(\"The pinned source archive expands too large\")\n        return data\n","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/third_party_source.py#L592-L628","documentation":"Path-safety validation applied to every tar member: a member name is rejected if it is empty, absolute (leading /), contains a backslash, has any empty/./.. path component, has a Windows drive prefix on any component, or does not start with the expected single root directory (_archive_root_name(spec)). This blocks path-traversal (zip-slip) and cross-platform escape techniques during extraction.","triggerScenarios":"Streaming extraction (_install_archive_source) encounters a tar entry like `../../etc/passwd`, `/abs/path`, `C:\\evil`, `pkg//file`, `.hidden/../x`, or an entry missing the expected `<repo>-<revision>/` root prefix (e.g. a repacked archive with a different top-level folder).","commonSituations":"Using a repacked/proxied tarball whose root directory was renamed (very common: GitHub codeload uses `<repo>-<full-sha>/` while mirrors may differ); a maliciously crafted archive in a supply-chain attack; archives produced by tools that emit `./`-prefixed entries.","solutions":["Ensure archive_url is the canonical artifact for the pinned revision (GitHub codeload tar.gz preserves the expected root folder name)","Inspect the tarball: tar -tzf source.tar.gz | head — verify the top-level directory matches _archive_root_name(spec) and no entry is absolute or contains ../","Re-pack the archive locally with the correct single root directory and re-pin it (update source_tree_digest)","If the root name derivation is wrong for your host, fix the spec fields feeding _archive_root_name (repo/revision)"],"exampleFix":"# before: mirror tarball with different root\narchive_url = \"https://mirror.example.com/foo.tar.gz\"  # root: foo/\n\n# after: canonical codeload tarball with expected root 'foo-<sha>/'\narchive_url = f\"https://codeload.github.com/org/foo/tar.gz/{spec.revision}\"","handlingStrategy":"validation","validationCode":"import tarfile\nwith tarfile.open(\"source.tar.gz\") as tf:\n    for m in tf:\n        parts = m.name.strip(\"/\").split(\"/\")\n        assert not m.name.startswith(\"/\") and \"\\\\\" not in m.name\n        assert all(p not in (\"\", \".\", \"..\") for p in parts)\n        assert parts[0] == expected_root, m.name","typeGuard":"def archive_paths_safe(archive: Path, expected_root: str) -> bool:\n    with tarfile.open(archive) as tf:\n        for m in tf:\n            name = m.name[:-1] if m.isdir() and m.name.endswith(\"/\") else m.name\n            parts = name.split(\"/\")\n            if (not name or name.startswith(\"/\") or \"\\\\\" in name\n                    or any(p in (\"\", \".\", \"..\") for p in parts)\n                    or parts[0] != expected_root):\n                return False\n    return True","tryCatchPattern":"try:\n    ensure_pinned_source(spec)\nexcept RuntimeError as e:\n    if \"Invalid path\" in str(e):\n        raise SystemExit(\"archive has unsafe/renamed root entries — repin to canonical tarball\")","preventionTips":["Only pin canonical per-commit archives whose single root directory is deterministic","Never repack archives with different root folder names; if you must repack, recompute and update the digests"],"tags":["security","path-traversal","tarfile","extraction","supply-chain"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}