{"record":{"id":"118dc92aa088f730","repo":"zed-industries/zed","slug":"sandbox-write-grant-was-redirected-to","errorCode":null,"errorMessage":"sandbox write grant {} was redirected to {}","messagePattern":"sandbox write grant (.+?) was redirected to (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/sandbox/src/util/canonical_path.rs","lineNumber":164,"sourceCode":"            // the symlink's *own* path (equal to `path`), so the comparison\n            // below wouldn't catch it.\n            let stat = nix::sys::stat::fstat(&fd).map_err(io::Error::from)?;\n            if stat.st_mode & libc::S_IFMT == libc::S_IFLNK {\n                return Err(io::Error::new(\n                    io::ErrorKind::PermissionDenied,\n                    format!(\n                        \"sandbox write grant {} is a symlink, not a directory\",\n                        path.display()\n                    ),\n                ));\n            }\n\n            // Load-bearing: the pinned inode's real path must still be exactly\n            // the approved canonical path. If any component became a symlink\n            // after approval, the fd resolves elsewhere and this diverges.\n            let current = std::fs::read_link(format!(\"/proc/self/fd/{}\", fd.as_raw_fd()))?;\n            if current != path {\n                return Err(io::Error::new(\n                    io::ErrorKind::PermissionDenied,\n                    format!(\n                        \"sandbox write grant {} was redirected to {}\",\n                        path.display(),\n                        current.display()\n                    ),\n                ));\n            }\n\n            Ok(Self {\n                path,\n                fd: std::sync::Arc::new(fd),\n            })\n        }\n        #[cfg(not(any(target_os = \"macos\", target_os = \"linux\")))]\n        {\n            Ok(Self { path })\n        }","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/sandbox/src/util/canonical_path.rs#L146-L182","documentation":"Guard in CanonicalPathBuf::from_canonical on Linux: the directory pinned by O_PATH at grant time is not the same directory the canonical path now points to — something replaced or redirected the grant path (e.g. a directory swapped for a symlink) between canonicalization and pinning. The sandbox refuses to grant writes to a moving target.","triggerScenarios":"Thrown at crates/sandbox/src/util/canonical_path.rs:164 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Remove or rename whatever is replacing the grant directory at runtime","Grant the stable canonical location instead of a path that gets swapped","Re-create the grant if a legitimate rename occurred"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5a9b9558db01a6b906cec2fb70a797affdc58cdd","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}