{"record":{"id":"2c03875a8bbf2654","repo":"jdx/mise","slug":"invalid-remote-cache-path-component","errorCode":null,"errorMessage":"invalid remote cache path component","messagePattern":"invalid remote cache path component","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/task_cache_store.rs","lineNumber":522,"sourceCode":"    }\n    if path.components().any(|component| {\n        matches!(\n            component,\n            Component::ParentDir | Component::RootDir | Component::Prefix(_)\n        )\n    }) {\n        bail!(\"remote cache path escapes its output root\");\n    }\n    Ok(())\n}\n\nfn cache_name(path: &Path) -> Result<String> {\n    let name = path\n        .file_name()\n        .and_then(|name| name.to_str())\n        .ok_or_else(|| eyre!(\"remote cache paths must be valid UTF-8\"))?;\n    if name.is_empty() || name == \".\" || name == \"..\" || name.contains(['/', '\\0']) {\n        bail!(\"invalid remote cache path component\");\n    }\n    Ok(name.to_string())\n}\n\nfn validate_cache_name(name: &str) -> Result<()> {\n    let path = Path::new(name);\n    if name.is_empty()\n        || name == \".\"\n        || name == \"..\"\n        || name.contains(['/', '\\\\', '\\0'])\n        || path.components().count() != 1\n        || !matches!(path.components().next(), Some(Component::Normal(_)))\n    {\n        bail!(\"invalid remote cache path component\");\n    }\n    Ok(())\n}\n","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/task/task_cache_store.rs#L504-L540","documentation":"cache_name extracts the final file-name component of a cache path for use as a store key. It fails with this message when the component is empty, '.', '..', or contains '/' or a NUL byte — none of which can be a single valid cache entry name. Callers use it in build_directory when assembling remote directory entries.","triggerScenarios":"Calling cache_name (via build_directory) with a path whose file_name() is '.', '..', empty after conversion, or which itself embeds '/' or '\\0' inside a single component name.","commonSituations":"Passing a directory path ending in '..' or '.', or hand-built names from environment/config values that were not sanitized.","solutions":["Ensure the path ends in a real file or directory name before calling build_directory.","Sanitize the component: reject or replace '.', '..', '/', and NUL in the name before use.","Log the offending path; if it comes from config, fix the configured value to a plain name."],"exampleFix":"// before\nlet name = format!(\"outputs/{}\");\n// after\nlet name = component.to_string(); // single sanitized name, no separators","handlingStrategy":"validation","validationCode":"fn is_valid_component(name: &str) -> bool {\n    !name.is_empty() && name != \".\" && name != \"..\"\n        && !name.contains(['/', '\\0'])\n}","typeGuard":"fn as_cache_component(p: &Path) -> Option<&str> {\n    let n = p.file_name()?.to_str()?;\n    is_valid_component(n).then_some(n)\n}","tryCatchPattern":"match build_directory(&path) {\n    Err(e) if e.to_string().contains(\"invalid remote cache path component\") => {\n        // log path and skip/sanitize the entry\n    }\n    r => r?,\n}","preventionTips":["Sanitize file names sourced from env vars or config before use","Keep entry names free of path separators; nest via child directories","Reject '.' and '..' at the source of name generation"],"tags":["path-validation","task-cache","invalid-component"],"backgroundTag":"invalid-identifier-format","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}