{"record":{"id":"6d6108d605431e20","repo":"xai-org/grok-build","slug":"invalid-worktree-id-from-dest-worktree-id","errorCode":null,"errorMessage":"invalid worktree id from dest: {worktree_id}","messagePattern":"invalid worktree id from dest: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-fast-worktree/src/api.rs","lineNumber":423,"sourceCode":"    ///\n    /// This is a **blocking** operation. Callers should use `spawn_blocking`\n    /// when calling from async contexts.\n    pub fn create(self) -> Result<WorktreeReport> {\n        // One canonical dest for the plan id, IPC idempotency key, and DB id.\n        let dest = crate::worktree::plan::canonicalize_for_id(&self.dest);\n        let worktree_id = {\n            #[cfg(feature = \"metadata\")]\n            {\n                self.worktree_id\n                    .unwrap_or_else(|| crate::worktree::plan::worktree_id_from_path(&dest))\n            }\n            #[cfg(not(feature = \"metadata\"))]\n            {\n                crate::worktree::plan::worktree_id_from_path(&dest)\n            }\n        };\n        if !crate::nfs::is_safe_worktree_id(&worktree_id) {\n            anyhow::bail!(\"invalid worktree id from dest: {worktree_id}\");\n        }\n\n        #[cfg(feature = \"metadata\")]\n        let meta_fields = (\n            self.worktree_kind,\n            self.session_id,\n            worktree_id.clone(),\n            self.source.clone(),\n            self.git_ref.clone(),\n            self.metadata,\n        );\n\n        let plan = crate::worktree::WorktreePlan {\n            source: self.source,\n            dest,\n            git_ref: self.git_ref,\n            parallelism: self.parallelism,\n            channel_buffer: self.channel_buffer,","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-fast-worktree/src/api.rs#L405-L441","documentation":"In `create`, after deriving a worktree id from the destination path (via the metadata feature or `worktree_id_from_path`), the id is validated with `nfs::is_safe_worktree_id`. If it fails (contains path separators, traversal sequences, or other unsafe characters/segments), creation aborts with this message. It protects against unsafe ids being stored/symlinked on NFS-backed storage.","triggerScenarios":"Calling a `create`-style API whose `dest` path yields an unsafe worktree id: a dest outside the managed root, a dest whose filename contains slashes or `..`/`.` traversal, or a custom/oddly nested dest that makes `worktree_id_from_path` return a multi-segment or empty id.","commonSituations":"Passing a destination path with `..` components or a trailing nested structure; pointing dest at a directory whose basename is not a valid id (empty, contains `/`); mixing feature flags (`metadata`) so the id is derived differently than expected; NFS-mounted storage where safe ids are mandatory.","solutions":["Inspect the error text: it interpolates the offending `worktree_id`; check it for `/`, `..`, empty segments, or illegal characters.","Pass a flat, simple destination path directly under the managed worktrees root so the derived id is a single safe component.","Pre-validate with `crate::nfs::is_safe_worktree_id(&worktree_id_from_path(dest))` before calling create.","Remove `..`, symlinks, or redundant separators from the dest path (e.g. use `std::fs::canonicalize` on the parent first).","If the id comes from an external caller, sanitize or reject it before constructing dest."],"exampleFix":"// before\nlet opts = CreateOptions::new().dest(\"/srv/worktrees/../evil/session1\");\napi.create(opts)?; // invalid worktree id from dest: ../evil/session1\n// after\nlet dest = Path::new(\"/srv/worktrees\").join(\"session1\"); // single safe component\nassert!(crate::nfs::is_safe_worktree_id(&crate::worktree::plan::worktree_id_from_path(&dest)));\napi.create(CreateOptions::new().dest(dest))?;\n","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn dest_id_is_safe(dest: &Path) -> bool {\n    match dest.file_name().and_then(|s| s.to_str()) {\n        Some(name) => !name.is_empty()\n            && !name.contains('/')\n            && name != \".\" && name != \"..\"\n            && crate::nfs::is_safe_worktree_id(name),\n        None => false,\n    }\n}\nassert!(dest_id_is_safe(&dest), \"dest yields unsafe worktree id\");","typeGuard":"fn is_safe_worktree_id(id: &str) -> bool {\n    !id.is_empty()\n        && !id.contains('/')\n        && !id.contains(\"..\")\n        && id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')\n}","tryCatchPattern":"match api.create(opts) {\n    Err(e) if e.to_string().starts_with(\"invalid worktree id from dest\") => {\n        eprintln!(\"fix dest path: {e}\");\n    }\n    r => r?,\n}","preventionTips":["Always build dest under the managed root with a single filename component","Canonicalize parent directories to eliminate '..' and symlink surprises","Pre-check ids with is_safe_worktree_id before calling create","Never accept raw user input as a worktree id without sanitization"],"tags":["path-traversal","validation","worktree","nfs"],"backgroundTag":"invalid-path-component","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}