{"record":{"id":"bc5bdf0021898417","repo":"openai/codex","slug":"externally-enforced-filesystem-permissions-cannot","errorCode":null,"errorMessage":"externally enforced filesystem permissions cannot be intersected safely","messagePattern":"externally enforced filesystem permissions cannot be intersected safely","errorType":"exception","errorClass":"PermissionIntersectionError","httpStatus":null,"severity":"error","filePath":"codex-rs/protocol/src/permission_profile_intersection.rs","lineNumber":23,"sourceCode":"use thiserror::Error;\n\nuse crate::models::PermissionProfile;\nuse crate::permissions::FileSystemAccessMode;\nuse crate::permissions::FileSystemPath;\nuse crate::permissions::FileSystemSandboxEntry;\nuse crate::permissions::FileSystemSandboxKind;\nuse crate::permissions::FileSystemSandboxPolicy;\nuse crate::permissions::FileSystemSpecialPath;\nuse crate::permissions::NetworkSandboxPolicy;\nuse crate::permissions::PROTECTED_METADATA_PATH_NAMES;\nuse crate::permissions::ReadDenyMatcher;\nuse crate::permissions::default_read_only_subpaths_for_writable_root;\nuse crate::permissions::project_roots_glob_pattern;\n\n/// A policy cannot be intersected without weakening either input.\n#[derive(Clone, Debug, Eq, Error, PartialEq)]\npub enum PermissionIntersectionError {\n    #[error(\"externally enforced filesystem permissions cannot be intersected safely\")]\n    ExternalSandbox,\n    #[error(\"platform-default filesystem permissions cannot be intersected safely\")]\n    PlatformDefaults,\n    #[error(\"unsupported permission path: {0}\")]\n    UnsupportedPath(String),\n}\n\n/// Intersects already-effective filesystem permissions and network access.\n///\n/// Both profiles must already be materialized for the same local executor and\n/// cwd. Concrete grant paths are canonicalized before comparison and in the\n/// result, so symlinks cannot acquire authority beyond either input.\n/// Unsupported policy shapes fail closed.\npub fn intersect_effective_permission_profiles(\n    authority: &PermissionProfile,\n    requested: &PermissionProfile,\n    cwd: &Path,\n) -> Result<PermissionProfile, PermissionIntersectionError> {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/protocol/src/permission_profile_intersection.rs#L5-L41","documentation":"PermissionIntersectionError::ExternalSandbox (codex-rs/protocol/src/permission_profile_intersection.rs:23-24) is returned by intersect_effective_permission_profiles when either input is PermissionProfile::External - permissions enforced by a sandbox outside Codex's own policy engine. As the module doc states, such a policy cannot be intersected without weakening an input, so the merge fails closed (checked first, at lines 42-46).","triggerScenarios":"Calling intersect_effective_permission_profiles(authority, requested, cwd) where either argument is PermissionProfile::External { .. } - for example a session launched inside a host-managed sandbox (outer Seatbelt/landlock/container) combined with any other profile.","commonSituations":"Host applications embedding Codex within their own sandbox; nested sandboxing; attempts to further restrict an externally enforced session by intersection.","solutions":["Do not intersect External profiles: use the stricter of the two profiles directly instead of merging.","Materialize both sides into concrete runtime permission profiles resolved for the same executor and cwd, then intersect - the function expects already-materialized inputs.","If you own the outer sandbox, express its restrictions as an explicit FileSystemSandboxPolicy rather than External."],"exampleFix":"// before:\nlet combined = intersect_effective_permission_profiles(&authority, &requested, &cwd)?;\n// authority is PermissionProfile::External -> ExternalSandbox error\n\n// after: branch before intersecting\nlet combined = if matches!(authority, PermissionProfile::External { .. })\n    || matches!(requested, PermissionProfile::External { .. })\n{\n    stricter_of(authority, requested) // no intersection for external sandboxes\n} else {\n    intersect_effective_permission_profiles(&authority, &requested, &cwd)?\n};","handlingStrategy":"type-guard","validationCode":"if matches!(authority, PermissionProfile::External { .. })\n    || matches!(requested, PermissionProfile::External { .. })\n{\n    // skip intersection; enforce the stricter profile as-is\n}","typeGuard":"fn is_external(p: &PermissionProfile) -> bool {\n    matches!(p, PermissionProfile::External { .. })\n}","tryCatchPattern":"Err(PermissionIntersectionError::ExternalSandbox) => {\n    // fail closed: keep the stricter profile unmodified; never weaken either side\n}","preventionTips":["Only intersect profiles materialized for the same executor and cwd.","Treat External as opaque: it cannot be merged, only obeyed or replaced.","Test the External path explicitly when hosting Codex in your own sandbox."],"tags":["rust","codex","sandbox","permissions","security","external"],"backgroundTag":"sandbox-policy-intersection-failed","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}