{"record":{"id":"d22c15733b0a2fca","repo":"rustfs/rustfs","slug":"rename-base-directory-contains-an-invalid-path-com","errorCode":null,"errorMessage":"rename base directory contains an invalid path component","messagePattern":"rename base directory contains an invalid path component","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/ecstore/src/disk/os.rs","lineNumber":2720,"sourceCode":"    {\n        use windows_sys::Wdk::Storage::FileSystem::{FILE_OPEN, FILE_OPEN_IF};\n        use windows_sys::Win32::Storage::FileSystem::{FILE_SHARE_READ, FILE_SHARE_WRITE};\n\n        let base_relative = publication_root.relative_path(base_dir)?;\n        let capacity = base_relative\n            .components()\n            .count()\n            .saturating_add(relative.components().count())\n            .saturating_add(1);\n        let mut handles = Vec::with_capacity(capacity);\n        handles.push(publication_root.directory.clone());\n        let mut guard = ExistingBaseDirectoryGuard::new(handles);\n        for component in base_relative.components() {\n            let Component::Normal(component) = component else {\n                if matches!(component, Component::CurDir) {\n                    continue;\n                }\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidInput,\n                    \"rename base directory contains an invalid path component\",\n                ));\n            };\n            let parent = guard\n                .handles\n                .last()\n                .ok_or_else(|| io::Error::other(\"Windows publication root guard is empty\"))?;\n            let child = open_windows_directory_component(parent, component, FILE_OPEN)?;\n            guard.handles.push(child);\n        }\n        for component in relative.components() {\n            let Component::Normal(component) = component else {\n                continue;\n            };\n            let parent = guard\n                .handles\n                .last()","sourceCodeStart":2702,"sourceCodeEnd":2738,"githubUrl":"https://github.com/rustfs/rustfs/blob/9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de/crates/ecstore/src/disk/os.rs#L2702-L2738","documentation":"Windows branch of mkdir_all_below_existing_base_std: while opening each component of base_dir relative to the publication root, any component that is not Normal (and not CurDir, which is skipped) — i.e. '..' or a root marker — is rejected with ErrorKind::InvalidInput. The base directory must be reachable purely through normal name components below the publication root so the chain of open directory handles cannot walk outside it.","triggerScenarios":"Windows rename publication where base_dir contains '..' or an absolute/root component relative to publication_root: volume roots like 'C:\\' leaking into the joined path, unnormalized '\\\\?\\' style paths, or a publication root configured at a different location than the base assumes.","commonSituations":"Deployments where the publication root and bucket directories are joined inconsistently at startup, path normalization changes during ports to Windows, or custom volume layouts.","solutions":["Normalize base_dir before the call and assert it starts with the publication root prefix","Audit how publication_root and the bucket base directories are joined at startup; fix the mismatched join","Add a Windows unit test pinning the exact path shapes for base vs publication root"],"exampleFix":"// before\nlet base = Path::new(r\"C:\\rustfs\\bucket\"); // contains a root component vs publication root\n\n// after\nlet base = publication_root.join(volume); // purely Normal components below the root","handlingStrategy":"validation","validationCode":"// before renaming on Windows, base must be purely Normal components below the root\nlet ok = base_dir.strip_prefix(publication_root).map(|rel| {\n    rel.components().all(|c| matches!(c, std::path::Component::Normal(_) | std::path::Component::CurDir))\n}).unwrap_or(false);\nif !ok { return Err(/* fix base construction */); }","typeGuard":null,"tryCatchPattern":"Match ErrorKind::InvalidInput with the 'base directory contains an invalid path component' message; normalize base_dir and fix the join against publication_root — not retryable.","preventionTips":["Normalize all storage paths at startup and assert the publication-root prefix relation","Never mix absolute roots or '\\\\?\\' style paths into base_dir construction"],"tags":["windows","path-validation","rename","security","invalid-input"],"backgroundTag":"path-traversal-guard","analyzedSha":"9e6e02ea09c86bedf44c7bd64a74ea02a0cff1de","analyzedAt":"2026-08-16T20:34:17.560Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}