{"record":{"id":"73e29048fd1b3a4e","repo":"astrid-runtime/astrid","slug":"legacy-source-entry-is-group-world-writable","errorCode":null,"errorMessage":"legacy source entry is group/world writable: {}","messagePattern":"legacy source entry is group/world writable: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs","lineNumber":786,"sourceCode":"            io::ErrorKind::InvalidData,\n            format!(\"legacy source contains a special entry: {}\", path.display()),\n        ));\n    }\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::MetadataExt as _;\n\n        if metadata.uid() != nix::unistd::getuid().as_raw() {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\n                    \"legacy source entry is not owned by the current user: {}\",\n                    path.display()\n                ),\n            ));\n        }\n        if metadata.mode() & 0o022 != 0 {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\n                    \"legacy source entry is group/world writable: {}\",\n                    path.display()\n                ),\n            ));\n        }\n        astrid_core::platform_fs::validate_no_extended_acl(path)?;\n        Ok(())\n    }\n    #[cfg(not(unix))]\n    {\n        validate_private_entry(path, metadata)\n    }\n}\n\nfn read_regular_file(\n    path: &Path,","sourceCodeStart":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/legacy_migration_barrier/host_fs.rs#L768-L804","documentation":"Under SourceAccess::OwnerControlled, entries must not be group- or world-writable: if metadata.mode() & 0o022 != 0 the migration fails with PermissionDenied. Group/world-writable files could be modified by other principals, so the owner-controlled guarantee (contents controlled solely by the owner) would not hold.","triggerScenarios":"Calling the migration API with SourceAccess::OwnerControlled where any file or directory in the source has mode bits 0o020 (group write) or 0o002 (other write) set — e.g. modes like 0664 files, 0775/0777 dirs, or umask-less tools writing 0666 files.","commonSituations":"Files created with a permissive umask (000) or by tools that force 0666; shared working directories using 0775; defaults of some archive extractors or editors; data copied from FAT/exFAT mounts with permissive modes.","solutions":["Tighten permissions: `chmod -R go-w <source>` (e.g. dirs to 0750, files to 0640)","Set a restrictive umask (022 or 077) and recreate/rewrite the offending files","Use SourceAccess::Private if the group/world-writable profile is acceptable in your environment"],"exampleFix":"// before: files are group-writable (0664)\nlet result = snapshot_path_with_access(path, SourceAccess::OwnerControlled);\n// Err: legacy source entry is group/world writable: ...\n\n// after: strip group/world write bits, then migrate\n// $ chmod -R go-w /home/alice/data\nlet result = snapshot_path_with_access(path, SourceAccess::OwnerControlled);","handlingStrategy":"validation","validationCode":"#[cfg(unix)]\nfn assert_not_group_or_world_writable(source: &std::path::Path) -> std::io::Result<()> {\n    use std::os::unix::fs::MetadataExt;\n    let mut stack = vec![source.to_path_buf()];\n    while let Some(dir) = stack.pop() {\n        for entry in std::fs::read_dir(&dir)? {\n            let path = entry?.path();\n            let md = std::fs::symlink_metadata(&path)?;\n            if md.mode() & 0o022 != 0 {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::PermissionDenied,\n                    format!(\"group/world writable: {}\", path.display()),\n                ));\n            }\n            if md.is_dir() {\n                stack.push(path);\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match snapshot_path_with_access(source, SourceAccess::OwnerControlled) {\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied\n        && e.to_string().contains(\"group/world writable\") =>\n    {\n        eprintln!(\"fix with: chmod -R go-w <source>\");\n    }\n    other => other?,\n}","preventionTips":["Run with a restrictive umask (022 or 077) when writing into the source tree","Audit with `find <source> -perm /022` before migrating","Avoid syncing source data from FAT/exFAT filesystems that force permissive modes","Tighten shared working directories to 0750/0640 instead of 0775/0664"],"tags":["filesystem","permissions","unix","validation","rust"],"backgroundTag":"permission-denied","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}