unslothai/unsloth · critical · RuntimeError
The pinned {spec.name} archive contains a non-regular file
Error message
The pinned {spec.name} archive contains a non-regular file What it means
During member iteration, any entry that is neither a directory nor a regular file (symlink, device, fifo, hardlink) — or a regular file with a negative size — is rejected before extraction. Extraction code only ever calls open('wb') and copy loops, so irregular members must never reach it; this blocks symlink/hardlink attacks where a later file write would follow a link out of the staging tree.
Source
Thrown at studio/backend/utils/third_party_source.py:657
member_count = 0
uncompressed_bytes = 0
extracted = set()
try:
with archive.open("rb") as compressed:
with gzip.GzipFile(fileobj = compressed, mode = "rb") as decompressed:
reader = _BoundedArchiveReader(decompressed, _ARCHIVE_MAX_TAR_BYTES)
with tarfile.open(fileobj = reader, mode = "r|") as bundle:
for member in bundle:
member_count += 1
if member_count > _ARCHIVE_MAX_MEMBERS:
raise RuntimeError(
f"The pinned {spec.name} archive has too many entries"
)
parts = _archive_member_parts(member, spec)
if member.isdir():
continue
if not member.isfile() or member.size < 0:
raise RuntimeError(
f"The pinned {spec.name} archive contains a non-regular file"
)
uncompressed_bytes += member.size
if uncompressed_bytes > _ARCHIVE_MAX_UNCOMPRESSED_BYTES:
raise RuntimeError(
f"The pinned {spec.name} archive expands too large"
)
if len(parts) < 3 or parts[1] != spec.package:
continue
relative = "/".join(parts[1:])
_package_path_parts(relative, spec, kind = "archive")
if relative in extracted:
raise RuntimeError(
f"The pinned {spec.name} archive contains duplicate files"
)
extracted.add(relative)
source_file = bundle.extractfile(member)
if source_file is None:View on GitHub (pinned to 203007d190)
Solutions
- List entry types: tar -tvzf source.tar.gz | grep -v '^[-d]' to find symlinks/devices in the archive
- Repack the source without symlinks (dereference with tar --dereference / cp -rL) and re-pin digests
- Use the canonical codeload tarball for the revision — GitHub source archives do not contain device nodes; if they contain symlinks, this pin cannot be used and needs a sanitized mirror
- If tampering is suspected (digest mismatch), treat as security incident
Example fix
# repack without symlinks, then re-pin # tar --dereference -czf clean.tar.gz foo-<sha>/ PinnedSource(..., source_tree_digest=recompute_digest(clean_tree))
Defensive patterns
Strategy: validation
Validate before calling
import tarfile
with tarfile.open("source.tar.gz") as tf:
for m in tf:
if not (m.isdir() or m.isfile()) or m.size < 0:
raise SystemExit(f"irregular member rejected: {m.name} type={m.type}") Type guard
def archive_members_regular(archive: Path) -> bool:
with tarfile.open(archive) as tf:
return all(m.isdir() or (m.isfile() and m.size >= 0) for m in tf) Try / catch
try:
ensure_pinned_source(spec)
except RuntimeError as e:
if "non-regular file" in str(e):
# repack with tar --dereference and re-pin digests Prevention
- Repack source trees with --dereference so no symlink entries reach the pin
- Treat any irregular-member failure on a canonical artifact as tampering and verify digests out-of-band
When it happens
Trigger: Archive contains a tar symlink entry (e.g. `pkg/lib -> /usr/lib`), a char/block device, a FIFO, or a member with size < 0 inside the target package subtree. Encountered when iterating a member that is not member.isdir() and fails member.isfile().
Common situations: Archives created on systems that preserve symlinks (many repos symlink docs/licenses); malicious archives planting symlinks to overwrite system files via later extraction; corrupt tar headers producing nonsense types/sizes.
Related errors
- Invalid path in the pinned {spec.name} source archive
- The pinned {spec.name} archive has too many entries
- The pinned {spec.name} archive contains duplicate files
- Symbolic-link folders are not allowed
- Linked folder is no longer a regular directory
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/cc43fbd006ff00e3.
Report an issue: GitHub.