mirror of
https://github.com/openai/codex.git
synced 2026-09-05 15:18:41 +00:00
config: default untrusted projects to read-only permissions
This commit is contained in:
@@ -735,11 +735,11 @@ impl ConfigToml {
|
||||
.or(if sandbox_mode_was_explicit {
|
||||
None
|
||||
} else {
|
||||
// If no sandbox_mode is set but this directory has a trust decision,
|
||||
// default to workspace-write except on unsandboxed Windows where we
|
||||
// If no sandbox_mode is set for a trusted directory, default
|
||||
// to workspace-write except on unsandboxed Windows where we
|
||||
// default to read-only.
|
||||
active_project.and_then(|p| {
|
||||
if p.is_trusted() || p.is_untrusted() {
|
||||
if p.is_trusted() {
|
||||
if cfg!(target_os = "windows")
|
||||
&& windows_sandbox_level == WindowsSandboxLevel::Disabled
|
||||
{
|
||||
|
||||
@@ -1423,11 +1423,7 @@ async fn system_allowed_permissions_keep_builtin_permission_fallbacks() -> anyho
|
||||
),
|
||||
(
|
||||
Some(TrustLevel::Untrusted),
|
||||
if cfg!(target_os = "windows") {
|
||||
BUILT_IN_PERMISSION_PROFILE_READ_ONLY
|
||||
} else {
|
||||
BUILT_IN_PERMISSION_PROFILE_WORKSPACE
|
||||
},
|
||||
BUILT_IN_PERMISSION_PROFILE_READ_ONLY,
|
||||
),
|
||||
(None, BUILT_IN_PERMISSION_PROFILE_READ_ONLY),
|
||||
] {
|
||||
|
||||
@@ -2549,6 +2549,50 @@ async fn empty_config_defaults_to_builtin_profile_for_trusted_project() -> std::
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn empty_config_defaults_to_builtin_read_only_for_untrusted_project() -> std::io::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let cwd = TempDir::new()?;
|
||||
let project_key = cwd.path().to_string_lossy().to_string();
|
||||
|
||||
let config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml {
|
||||
projects: Some(HashMap::from([(
|
||||
project_key,
|
||||
ProjectConfig {
|
||||
trust_level: Some(TrustLevel::Untrusted),
|
||||
},
|
||||
)])),
|
||||
..Default::default()
|
||||
},
|
||||
ConfigOverrides {
|
||||
cwd: Some(cwd.path().to_path_buf()),
|
||||
..Default::default()
|
||||
},
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert_eq!(
|
||||
config
|
||||
.permissions
|
||||
.active_permission_profile()
|
||||
.as_ref()
|
||||
.map(|active| active.id.as_str()),
|
||||
Some(BUILT_IN_PERMISSION_PROFILE_READ_ONLY)
|
||||
);
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected untrusted project fallback to allow reads, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected untrusted project fallback to use :read-only, policy: {policy:?}"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn implicit_builtin_workspace_profile_preserves_sandbox_workspace_write_settings()
|
||||
-> std::io::Result<()> {
|
||||
@@ -8566,7 +8610,7 @@ async fn test_load_config_rejects_legacy_ollama_chat_provider_with_helpful_error
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_untrusted_project_gets_workspace_write_sandbox() -> anyhow::Result<()> {
|
||||
async fn test_untrusted_project_gets_read_only_sandbox() -> anyhow::Result<()> {
|
||||
let config_with_untrusted = r#"
|
||||
[projects."/tmp/test"]
|
||||
trust_level = "untrusted"
|
||||
@@ -8587,18 +8631,10 @@ trust_level = "untrusted"
|
||||
)
|
||||
.await;
|
||||
|
||||
// Verify that untrusted projects get WorkspaceWrite (or ReadOnly on Windows due to downgrade)
|
||||
if cfg!(target_os = "windows") {
|
||||
assert!(
|
||||
matches!(resolution, SandboxPolicy::ReadOnly { .. }),
|
||||
"Expected ReadOnly on Windows, got {resolution:?}"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
matches!(resolution, SandboxPolicy::WorkspaceWrite { .. }),
|
||||
"Expected WorkspaceWrite for untrusted project, got {resolution:?}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
matches!(resolution, SandboxPolicy::ReadOnly { .. }),
|
||||
"Expected ReadOnly for untrusted project, got {resolution:?}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -8955,24 +8991,13 @@ async fn test_untrusted_project_gets_unless_trusted_approval_policy() -> anyhow:
|
||||
"Expected UnlessTrusted approval policy for untrusted project"
|
||||
);
|
||||
|
||||
// Verify that untrusted projects still get WorkspaceWrite sandbox (or ReadOnly on Windows)
|
||||
if cfg!(target_os = "windows") {
|
||||
assert!(
|
||||
matches!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
SandboxPolicy::ReadOnly { .. }
|
||||
),
|
||||
"Expected ReadOnly on Windows"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
matches!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
SandboxPolicy::WorkspaceWrite { .. }
|
||||
),
|
||||
"Expected WorkspaceWrite sandbox for untrusted project"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
matches!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
SandboxPolicy::ReadOnly { .. }
|
||||
),
|
||||
"Expected ReadOnly sandbox for untrusted project"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub(crate) fn default_builtin_permission_profile_name(
|
||||
active_project: &ProjectConfig,
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
) -> &'static str {
|
||||
if (active_project.is_trusted() || active_project.is_untrusted())
|
||||
if active_project.is_trusted()
|
||||
&& !(cfg!(target_os = "windows") && windows_sandbox_level == WindowsSandboxLevel::Disabled)
|
||||
{
|
||||
BUILT_IN_WORKSPACE_PROFILE
|
||||
|
||||
Reference in New Issue
Block a user