jdx/mise · error
remote task path escapes its Git checkout: {}
Error message
remote task path escapes its Git checkout: {} What it means
When a remote task (fetched from a Git URL) is resolved to a local path, mise validates that the resolved path — including via symlink_metadata/canonicalize — still lives inside the cloned checkout root. If the canonicalized path escapes the checkout (e.g. via a symlink pointing outside), mise refuses with this error, guarding against path traversal from untrusted task repositories.
Source
Thrown at src/task/task_file_providers/remote_task_git.rs:81
url_without_path: url_without_path.to_string(),
path: path.to_string(),
branch,
}
}
}
/// Ensure a remote task path resolves inside its Git checkout and points at a
/// regular file or directory.
pub(crate) fn validate_remote_git_path(
checkout_root: &Path,
path: &Path,
) -> Result<std::fs::Metadata> {
let metadata = path.symlink_metadata()?;
if !path
.canonicalize()?
.starts_with(checkout_root.canonicalize()?)
{
eyre::bail!(
"remote task path escapes its Git checkout: {}",
display_path(path)
);
}
if metadata.file_type().is_file() || metadata.file_type().is_dir() {
return Ok(metadata);
}
eyre::bail!(
"remote task path is not a regular file or directory: {}",
display_path(path)
)
}
impl RemoteTaskGit {
/// Make fetched task files executable while leaving task include directories intact.
fn prepare_remote_path(checkout_root: &Path, path: &Path) -> Result<()> {
if validate_remote_git_path(checkout_root, path)?
.file_type()View on GitHub (pinned to afd2eddd3a)
Solutions
- Fix the remote task path to point inside the checkout (no ../ traversal, no outbound symlinks)
- Remove or replace outbound symlinks in the task repository
- Re-clone the repository so paths resolve within the new checkout root
- If you own the repo, restructure so task files are real files inside the repo
Example fix
# before: remote task path escaping the checkout source = "https://github.com/org/tasks#../../host-tool" # after source = "https://github.com/org/tasks#tasks/build.toml"
Defensive patterns
Strategy: validation
Validate before calling
import fs from "fs";
import path from "path";
function insideCheckout(root, p) {
const realRoot = fs.realpathSync(root);
const realP = fs.realpathSync(path.join(root, p));
return realP.startsWith(realRoot + path.sep);
} Type guard
fn stays_in_checkout(root: &Path, p: &Path) -> bool {
match (p.canonicalize(), root.canonicalize()) {
(Ok(p), Ok(r)) => p.starts_with(r),
_ => false,
}
} Try / catch
try {
const meta = fs.lstatSync(taskPath);
if (meta.isSymbolicLink() && !insideCheckout(checkoutRoot, taskPath)) {
throw new Error("remote task path escapes checkout");
}
} catch (e) {
console.error("Use a path inside the cloned repo and avoid outbound symlinks");
throw e;
} Prevention
- Never configure remote task paths with ../ components
- Audit remote task repos for symlinks leaving the checkout
- Clone remote task repos fresh rather than reusing moved directories
- Treat remote tasks as untrusted and pin them to a commit SHA
When it happens
Trigger: validate_remote_git_path (called by resolve_git_url_to_path and prepare_remote_path) raises when path.canonicalize() does not start with checkout_root.canonicalize() — a symlink inside the checkout points outside, the configured subpath contains ../ traversal, or the checkout moved so canonicalization diverges.
Common situations: A remote task repo where the task file is a symlink to another location on the machine; a configured remote task subpath like ../../something; a moved/renamed checkout confusing path resolution; \\wsl$ vs native path mismatches on Windows.
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
- brew-cask:{}: git only_path must stay within the checkout
- unsafe source repository path
- [dotfiles]."{}": target is not a safe OCI path
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/8809ad4449ed491f.
Report an issue: GitHub.