denoland/deno · critical
refusing tar entry with traversal path: {}
Error message
refusing tar entry with traversal path: {} What it means
Thrown while extracting the downloaded LAUFEY runtime tar archive: an entry's path contains a `..` (ParentDir) or root (RootDir) component, a classic path-traversal (tar-slip) attempt. This is a deliberate hard error — the underlying `unpack_in` would silently SKIP such entries, so the code pre-checks and refuses the whole archive instead. Since the archive passed the SHA-256 check before extraction, this indicates a malicious or corrupted UPSTREAM release, not a network issue.
Source
Thrown at cli/tools/desktop.rs:2228
let mut archive = tar::Archive::new(decoder);
// Strip mode bits from archive entries: a tampered archive could
// otherwise ship setuid/setgid binaries into the deno cache. Files keep
// the umask-applied default; we re-add execute bits below for entries
// that need them.
archive.set_preserve_permissions(false);
for entry in archive.entries()? {
let mut entry = entry?;
let entry_path = entry.path()?.into_owned();
// Defence in depth — pre-check `..` / root before handing to
// `unpack_in`, since we want a hard error rather than the silent
// skip that `unpack_in` does for a rejected entry.
if entry_path.components().any(|c| {
matches!(
c,
std::path::Component::ParentDir | std::path::Component::RootDir
)
}) {
bail!(
"refusing tar entry with traversal path: {}",
entry_path.display()
);
}
// `unpack_in` (vs. `unpack(absolute_path)`) makes tar enforce its
// symlink + hardlink target containment too: a tar with entry A as
// symlink `foo -> ../../etc` followed by entry B writing
// `foo/passwd` would otherwise escape `dest`.
if !entry.unpack_in(dest)? {
bail!(
"refusing tar entry that would unpack outside dest: {}",
entry_path.display()
);
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let dest_path = dest.join(&entry_path);View on GitHub (pinned to f7822238ca)
Solutions
- Do NOT bypass the check or extract the archive manually — treat it as hostile until proven otherwise.
- Inspect the archive safely: `tar -tvf <archive>` and look for absolute paths or `..` segments in the listing.
- Clear the LAUFEY cache and re-download; if the mismatch reproduces, report it immediately to the deno/laufey maintainers with the archive name and URL.
Defensive patterns
Strategy: try-catch
Try / catch
# Never bypass; surface as a security failure if deno desktop main.ts 2>&1 | tee /tmp/d.log && grep -q "refusing tar entry" /tmp/d.log; then echo "SECURITY: malicious/corrupt runtime archive — report upstream" >&2; exit 2 fi
Prevention
- Keep the LAUFEY cache read-only for untrusted users to avoid post-verification tampering.
- Pin to official Deno releases so archive pins and extractor checks stay in sync.
- Treat any traversal hit as an upstream incident: report the archive name and URL.
When it happens
Trigger: A crafted laufey release tarball containing entries like `../../etc/passwd` or `/etc/launcher`; a corrupted (bit-rotted) cache producing garbage paths; an upstream packaging bug that emitted absolute paths in the tar.
Common situations: Almost never in normal use — the checksum gate means you see this only if the pinned release itself contains such entries (compromised or mis-built release) or the local cache was corrupted after verification.
Related errors
- refusing tar entry that would unpack outside dest: {}
- refusing zip entry with unsafe path: {}
- refusing zip entry with traversal path: {}
- refusing symlink entry in laufey archive: {}
- ${prefix}Linter plugin must be an object
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/9e8603fac8846115.
Report an issue: GitHub.