{"record":{"id":"bd0dac6b57729d41","repo":"Hmbown/CodeWhale","slug":"private-sidecar-file-path-must-be-one-regular-filesystem","errorCode":null,"errorMessage":"private sidecar file {path} must be one regular filesystem link","messagePattern":"private sidecar file (.+?) must be one regular filesystem link","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_manager.rs","lineNumber":191,"sourceCode":"    }\n    #[cfg(windows)]\n    {\n        use std::os::windows::fs::OpenOptionsExt as _;\n        use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT;\n        options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT);\n    }\n    let file = options.open(path)?;\n    validate_private_regular_file(&file, path)?;\n    Ok(file)\n}\n\n#[cfg(unix)]\nfn validate_private_regular_file(file: &fs::File, path: &Path) -> io::Result<()> {\n    use std::os::unix::fs::MetadataExt as _;\n\n    let metadata = file.metadata()?;\n    if !metadata.is_file() || metadata.nlink() != 1 {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"private sidecar file {} must be one regular filesystem link\",\n                path.display()\n            ),\n        ));\n    }\n    Ok(())\n}\n\n#[cfg(windows)]\nfn validate_private_regular_file(file: &fs::File, path: &Path) -> io::Result<()> {\n    use std::os::windows::fs::MetadataExt as _;\n    use std::os::windows::io::AsRawHandle as _;\n    use windows_sys::Win32::Storage::FileSystem::{\n        BY_HANDLE_FILE_INFORMATION, FILE_ATTRIBUTE_REPARSE_POINT, GetFileInformationByHandle,\n    };\n","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/session_manager.rs#L173-L209","documentation":"validate_private_regular_file (unix) checks that a freshly opened sidecar file (lock or read file) is a regular file with exactly one hard link (nlink == 1). Extra links mean someone hard-linked the private sidecar, and non-regular files mean it is a device/fifo or the open resolved through something unexpected — both break the privacy/conflict-detection assumptions, so the open fails with InvalidData.","triggerScenarios":"open_private_lock_file or open_private_read_file opening a session sidecar whose inode has nlink > 1 (hard-linked elsewhere) or whose metadata is not a regular file; typically detected right after O_CREAT-style open under a private directory.","commonSituations":"An attacker or accident hard-linked the lock file into another location to subvert or share locking; backup/restore tooling recreated sidecars with hard links; a symlink or FIFO was placed where the sidecar should be; the sessions directory was restored from an rsync/hard-link-based backup.","solutions":["Inspect the sidecar with `stat` and `find -samefile`; remove the extra hard link(s) so nlink returns to 1.","Delete the suspect sidecar (lock files are safe to recreate) and let the manager recreate it.","Check the sessions directory for tampering — unexpected hard links or special files — before resuming.","Restore the directory from a clean backup if tooling (rsync -H, git hard-link caches) rewired links."],"exampleFix":"// before\n$ stat sessions/abc.lock  # Links: 2\n// after\n$ rm sessions/abc.lock    # manager recreates a fresh single-link lock on next open","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match open_private_lock_file(&path) {\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => {\n        // suspect tampering or hard-linked sidecar: surface a loud warning,\n        // do not silently recreate over a possibly malicious link\n    }\n    other => other?,\n}","preventionTips":["Keep session state directories private (0700) so nothing else can link into them.","Avoid hard-link-based backup/sync tools (rsync -H) against the sessions directory.","Investigate any InvalidData on sidecar open as potential tampering, not a transient fault.","Delete and let the manager recreate lock sidecars rather than repairing links in place."],"tags":["filesystem","security","unix","hardlink"],"backgroundTag":"internal-invariant-violation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}