mirror of
https://github.com/openai/codex.git
synced 2026-10-25 07:55:34 +00:00
Preserve permissions when updating session metadata (#41464)
## What changed - Defer legacy sandbox policy projection until a working-directory change may require rebinding project-root writes. - Keep client name and version updates from resolving filesystem paths or altering the existing permission snapshot. ## Testing - Add regression coverage for updating client metadata with a managed, restricted filesystem policy that includes both a writable path and a nested denied path. GitOrigin-RevId: d84dbcd09b9d1961a11b2889d79479e30eb54149
This commit is contained in:
@@ -351,10 +351,8 @@ impl SessionConfiguration {
|
||||
current_environments: &[TurnEnvironmentSelection],
|
||||
) -> ConstraintResult<Self> {
|
||||
let mut next_configuration = self.clone();
|
||||
let current_sandbox_policy = self.sandbox_policy(current_environments);
|
||||
let current_file_system_sandbox_policy =
|
||||
self.file_system_sandbox_policy(current_environments);
|
||||
let current_network_sandbox_policy = self.network_sandbox_policy();
|
||||
let file_system_policy_has_rebindable_project_root_write =
|
||||
current_file_system_sandbox_policy
|
||||
.entries
|
||||
@@ -437,35 +435,37 @@ impl SessionConfiguration {
|
||||
network_sandbox_policy,
|
||||
),
|
||||
)?;
|
||||
} else if cwd_changed
|
||||
&& file_system_policy_has_rebindable_project_root_write
|
||||
&& current_file_system_sandbox_policy.is_semantically_equivalent_to(
|
||||
} else if cwd_changed && file_system_policy_has_rebindable_project_root_write {
|
||||
// Compatibility projection can resolve filesystem paths. Only compute it
|
||||
// when a cwd-bound legacy policy might need rebinding.
|
||||
let current_sandbox_policy = self.sandbox_policy(current_environments);
|
||||
if current_file_system_sandbox_policy.is_semantically_equivalent_to(
|
||||
&FileSystemSandboxPolicy::from_legacy_sandbox_policy_preserving_deny_entries(
|
||||
¤t_sandbox_policy,
|
||||
self.cwd(),
|
||||
¤t_file_system_sandbox_policy,
|
||||
),
|
||||
self.cwd(),
|
||||
)
|
||||
{
|
||||
// Preserve richer split policies across cwd-only updates; only
|
||||
// rederive when the session is already using a structurally
|
||||
// cwd-bound legacy bridge.
|
||||
let file_system_sandbox_policy =
|
||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_preserving_deny_entries(
|
||||
¤t_sandbox_policy,
|
||||
next_configuration.cwd(),
|
||||
¤t_file_system_sandbox_policy,
|
||||
);
|
||||
next_configuration
|
||||
.permission_profile_state
|
||||
.set_legacy_permission_profile(
|
||||
PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
SandboxEnforcement::from_legacy_sandbox_policy(¤t_sandbox_policy),
|
||||
&file_system_sandbox_policy,
|
||||
current_network_sandbox_policy,
|
||||
),
|
||||
)?;
|
||||
) {
|
||||
// Preserve richer split policies across cwd-only updates; only
|
||||
// rederive when the session is already using a structurally
|
||||
// cwd-bound legacy bridge.
|
||||
let file_system_sandbox_policy =
|
||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_preserving_deny_entries(
|
||||
¤t_sandbox_policy,
|
||||
next_configuration.cwd(),
|
||||
¤t_file_system_sandbox_policy,
|
||||
);
|
||||
next_configuration
|
||||
.permission_profile_state
|
||||
.set_legacy_permission_profile(
|
||||
PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
SandboxEnforcement::from_legacy_sandbox_policy(¤t_sandbox_policy),
|
||||
&file_system_sandbox_policy,
|
||||
self.network_sandbox_policy(),
|
||||
),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
if let Some(app_server_client_name) = updates.app_server_client_name.clone() {
|
||||
next_configuration.app_server_client_name = Some(app_server_client_name);
|
||||
|
||||
@@ -5328,6 +5328,55 @@ async fn resolved_environments_for_configuration(
|
||||
(environment_manager, turn_environments.snapshot().await)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn session_configuration_apply_client_metadata_preserves_permissions() {
|
||||
let mut configuration = make_session_configuration_for_tests().await;
|
||||
let workspace = tempfile::tempdir().expect("create workspace");
|
||||
let cwd = workspace.path().abs();
|
||||
configuration.legacy_fallback_cwd = cwd.clone();
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
SandboxEnforcement::Managed,
|
||||
&FileSystemSandboxPolicy::restricted(vec![
|
||||
FileSystemSandboxEntry::new(
|
||||
FileSystemPath::Path {
|
||||
path: cwd.join("writable").into(),
|
||||
},
|
||||
FileSystemAccessMode::Write,
|
||||
),
|
||||
FileSystemSandboxEntry::new(
|
||||
FileSystemPath::Path {
|
||||
path: cwd.join("writable/private").into(),
|
||||
},
|
||||
FileSystemAccessMode::Deny,
|
||||
),
|
||||
]),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
);
|
||||
configuration
|
||||
.set_permission_profile_for_tests(permission_profile)
|
||||
.expect("set custom permission profile");
|
||||
let expected = configuration.thread_settings_snapshot(&[]);
|
||||
let updated = configuration
|
||||
.apply(
|
||||
&SessionSettingsUpdate {
|
||||
app_server_client_name: Some("codex-tui".to_string()),
|
||||
app_server_client_version: Some("1.0.0".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
&[],
|
||||
)
|
||||
.expect("update client metadata");
|
||||
|
||||
assert_eq!(updated.thread_settings_snapshot(&[]), expected);
|
||||
assert_eq!(
|
||||
(
|
||||
updated.app_server_client_name,
|
||||
updated.app_server_client_version
|
||||
),
|
||||
(Some("codex-tui".to_string()), Some("1.0.0".to_string())),
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn session_configuration_apply_preserves_profile_file_system_policy_on_cwd_only_update() {
|
||||
let mut session_configuration = make_session_configuration_for_tests().await;
|
||||
|
||||
Reference in New Issue
Block a user