openai/codex · error · PermissionIntersectionError

platform-default filesystem permissions cannot be intersecte

Error message

platform-default filesystem permissions cannot be intersected safely

What it means

PermissionIntersectionError::PlatformDefaults (codex-rs/protocol/src/permission_profile_intersection.rs:25-26) is raised inside normalize_policy (lines 277-279, and for FileSystemSpecialPath::Minimal at 339-341) when a policy being intersected still includes platform defaults - include_platform_defaults() is true or the Minimal special path is present. Platform defaults resolve per-OS and per-executor, so an intersection could silently diverge from what either input actually grants; the merge fails closed.

Source

Thrown at codex-rs/protocol/src/permission_profile_intersection.rs:25

use crate::models::PermissionProfile;
use crate::permissions::FileSystemAccessMode;
use crate::permissions::FileSystemPath;
use crate::permissions::FileSystemSandboxEntry;
use crate::permissions::FileSystemSandboxKind;
use crate::permissions::FileSystemSandboxPolicy;
use crate::permissions::FileSystemSpecialPath;
use crate::permissions::NetworkSandboxPolicy;
use crate::permissions::PROTECTED_METADATA_PATH_NAMES;
use crate::permissions::ReadDenyMatcher;
use crate::permissions::default_read_only_subpaths_for_writable_root;
use crate::permissions::project_roots_glob_pattern;

/// A policy cannot be intersected without weakening either input.
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum PermissionIntersectionError {
    #[error("externally enforced filesystem permissions cannot be intersected safely")]
    ExternalSandbox,
    #[error("platform-default filesystem permissions cannot be intersected safely")]
    PlatformDefaults,
    #[error("unsupported permission path: {0}")]
    UnsupportedPath(String),
}

/// Intersects already-effective filesystem permissions and network access.
///
/// Both profiles must already be materialized for the same local executor and
/// cwd. Concrete grant paths are canonicalized before comparison and in the
/// result, so symlinks cannot acquire authority beyond either input.
/// Unsupported policy shapes fail closed.
pub fn intersect_effective_permission_profiles(
    authority: &PermissionProfile,
    requested: &PermissionProfile,
    cwd: &Path,
) -> Result<PermissionProfile, PermissionIntersectionError> {
    if matches!(authority, PermissionProfile::External { .. })
        || matches!(requested, PermissionProfile::External { .. })

View on GitHub (pinned to 339751715c)

Solutions

  1. Materialize platform defaults for the concrete executor and OS into explicit policy entries before intersecting.
  2. Rebuild the profile with include_platform_defaults off once defaults are expanded.
  3. Replace FileSystemSpecialPath::Minimal with its concrete entry set before merging.

Example fix

// before:
let merged = intersect_effective_permission_profiles(&a, &b, &cwd)?;
// a.include_platform_defaults() == true -> PlatformDefaults error

// after: expand defaults into concrete entries, then intersect
let a = materialize_platform_defaults(a, &cwd)?; // no platform defaults left
let merged = intersect_effective_permission_profiles(&a, &b, &cwd)?;
Defensive patterns

Strategy: validation

Validate before calling

if authority.file_system_sandbox_policy().include_platform_defaults()
    || requested.file_system_sandbox_policy().include_platform_defaults()
{
    // expand platform defaults into explicit entries before intersecting
}

Type guard

fn includes_platform_defaults(p: &PermissionProfile) -> bool {
    p.file_system_sandbox_policy().include_platform_defaults()
}

Try / catch

Err(PermissionIntersectionError::PlatformDefaults) => {
    // expand defaults for this executor and retry the intersection once
}

Prevention

When it happens

Trigger: intersect_effective_permission_profiles on two differing, non-Unrestricted, non-Disabled profiles where either side was built with include_platform_defaults = true or carries the Minimal special path.

Common situations: User configs layering grants on top of OS defaults; cross-platform configs where defaults differ; profiles forwarded to intersection without being materialized for the concrete executor.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/81ef4be0210ae302. Report an issue: GitHub.