jdx/mise · critical

vfox plugin archive contains an unsafe path

Error message

vfox plugin archive contains an unsafe path

What it means

When validating a vfox plugin archive before extraction, mise checks every entry path for unsafe components. Any path component that is not Normal (e.g. `..`, absolute/root, prefix components), or a name containing backslashes/colons or a `.git`/state-file name, causes the archive to be rejected as containing an unsafe (path-traversal) path.

Source

Thrown at src/plugins/packslip.rs:225

pub(crate) fn validate_archive(path: &Path) -> Result<()> {
    let reader = flate2::read::GzDecoder::new(std::fs::File::open(path)?);
    let mut archive = jdx_tar::Archive::new(reader);
    for entry in archive.entries()? {
        let entry = entry?;
        ensure!(
            matches!(
                entry.entry_type(),
                jdx_tar::EntryType::File | jdx_tar::EntryType::Directory
            ),
            "vfox plugin archive contains a link or special file"
        );
        let path = entry.path()?;
        for component in path.components() {
            if component == Component::CurDir {
                continue;
            }
            let Component::Normal(name) = component else {
                bail!("vfox plugin archive contains an unsafe path");
            };
            let name = name.to_string_lossy();
            ensure!(
                !name.contains(['\\', ':'])
                    && !name.eq_ignore_ascii_case(".git")
                    && !name.eq_ignore_ascii_case(STATE_FILE),
                "vfox plugin archive contains a reserved or unsafe path"
            );
        }
    }
    Ok(())
}

pub(crate) fn validate_layout(path: &Path) -> Result<()> {
    ensure!(
        path.join("metadata.lua").is_file(),
        "vfox plugin archive must contain metadata.lua at its root"
    );

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Obtain the plugin archive from the trusted upstream source / re-download it; treat this as a potentially malicious archive and don't extract it manually elsewhere.
  2. Repackage the archive correctly: build it with relative paths from the plugin root, excluding .git, using forward slashes and no `..` or drive-letter components.
  3. Report the offending plugin/archive to its maintainer if the unsafe paths appear in the official release.

Example fix

// before (repackaging includes traversal + .git)
tar -czf plugin.tar.gz ../my-plugin/.git ../my-plugin
// after
cd my-plugin && tar -czf ../plugin.tar.gz --exclude=.git .
Defensive patterns

Strategy: try-catch

Validate before calling

import std::path::{Path, Component};
fn archive_entries_look_safe(entries: &[String]) -> bool {
    entries.iter().all(|e| {
        Path::new(e).components().all(|c| matches!(c, Component::Normal(n) if !n.to_string_lossy().contains(['\\',':']) && !n.eq_ignore_ascii_case(".git")))
    })
}

Try / catch

match install_vfox_plugin(archive) {
    Err(e) if e.to_string().contains("unsafe path") => {
        eprintln!("archive rejected as unsafe (possible path traversal); use a trusted source");
        // do not extract manually
    }
    r => r,
}

Prevention

When it happens

Trigger: Installing/updating a vfox plugin whose archive contains entries with `..` components, absolute paths, Windows drive/prefix components, or names with `\` or `:` or a top-level `.git`/state file — caught during validate_archive in packslip.rs.

Common situations: A maliciously crafted or compromised plugin archive attempting zip-slip traversal; archives built on Windows leaking drive-letter or backslash paths; archives that accidentally include their .git directory; corrupted archives with mangled entry names.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/061ccf2874da5b32. Report an issue: GitHub.