diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs
index cbdbee0402e..8d1797e7247 100644
--- a/codex-rs/tui/src/app.rs
+++ b/codex-rs/tui/src/app.rs
@@ -10,6 +10,7 @@ use crate::app_event::AppEvent;
 use crate::app_event::ExitMode;
 use crate::app_event::FeedbackCategory;
 use crate::app_event::HistoryLookupResponse;
+use crate::app_event::PermissionProfileSelection;
 use crate::app_event::RateLimitRefreshOrigin;
 use crate::app_event::RealtimeAudioDeviceKind;
 #[cfg(target_os = "windows")]
@@ -484,7 +485,7 @@ pub(crate) struct App {
     harness_overrides: ConfigOverrides,
     loader_overrides: LoaderOverrides,
     runtime_approval_policy_override: Option<AskForApproval>,
-    runtime_permission_profile_override: Option<PermissionProfile>,
+    runtime_permission_profile_override: Option<RuntimePermissionProfileOverride>,
 
     pub(crate) file_search: FileSearchManager,
 
@@ -554,6 +555,23 @@ pub(crate) struct App {
     pending_hook_enabled_writes: HashMap<String, Option<bool>>,
 }
 
+#[derive(Debug, Clone, PartialEq)]
+struct RuntimePermissionProfileOverride {
+    permission_profile: PermissionProfile,
+    active_permission_profile: Option<ActivePermissionProfile>,
+    network: Option<crate::legacy_core::config::NetworkProxySpec>,
+}
+
+impl RuntimePermissionProfileOverride {
+    fn from_config(config: &Config) -> Self {
+        Self {
+            permission_profile: config.permissions.permission_profile().clone(),
+            active_permission_profile: config.permissions.active_permission_profile(),
+            network: config.permissions.network.clone(),
+        }
+    }
+}
+
 fn active_turn_not_steerable_turn_error(error: &TypedRequestError) -> Option<AppServerTurnError> {
     let TypedRequestError::Server { source, .. } = error else {
         return None;
diff --git a/codex-rs/tui/src/app/config_persistence.rs b/codex-rs/tui/src/app/config_persistence.rs
index 3955b5ab09d..d4fdebad89d 100644
--- a/codex-rs/tui/src/app/config_persistence.rs
+++ b/codex-rs/tui/src/app/config_persistence.rs
@@ -5,6 +5,8 @@
 //! loop.
 
 use super::*;
+#[cfg(target_os = "windows")]
+use codex_utils_approval_presets::ApprovalPreset;
 
 impl App {
     pub(super) async fn rebuild_config_for_cwd(&self, cwd: PathBuf) -> Result<Config> {
@@ -21,6 +23,161 @@ impl App {
             .wrap_err_with(|| format!("Failed to rebuild config for cwd {cwd_display}"))
     }
 
+    pub(super) async fn rebuild_config_for_permission_profile(
+        &self,
+        profile_id: &str,
+    ) -> Result<Config> {
+        let mut overrides = self.harness_overrides.clone();
+        overrides.cwd = Some(self.chat_widget.config_ref().cwd.to_path_buf());
+        overrides.sandbox_mode = None;
+        overrides.permission_profile = None;
+        overrides.default_permissions = Some(profile_id.to_string());
+        ConfigBuilder::default()
+            .codex_home(self.config.codex_home.to_path_buf())
+            .cli_overrides(self.cli_kv_overrides.clone())
+            .harness_overrides(overrides)
+            .loader_overrides(self.loader_overrides.clone())
+            .build()
+            .await
+            .wrap_err_with(|| {
+                format!("Failed to rebuild config for permission profile {profile_id}")
+            })
+    }
+
+    #[cfg(target_os = "windows")]
+    pub(super) async fn permission_profile_for_windows_setup(
+        &self,
+        preset: &ApprovalPreset,
+        profile_selection: Option<&PermissionProfileSelection>,
+    ) -> Result<PermissionProfile> {
+        match profile_selection {
+            Some(selection) => Ok(self
+                .rebuild_config_for_permission_profile(selection.profile_id.as_str())
+                .await?
+                .permissions
+                .permission_profile()
+                .clone()),
+            None => Ok(preset.permission_profile.clone()),
+        }
+    }
+
+    pub(super) async fn apply_permission_profile_selection(
+        &mut self,
+        selection: PermissionProfileSelection,
+    ) -> bool {
+        let PermissionProfileSelection {
+            profile_id,
+            approval_policy,
+            approvals_reviewer,
+            display_label,
+        } = selection;
+        let selected_config = match self
+            .rebuild_config_for_permission_profile(profile_id.as_str())
+            .await
+        {
+            Ok(config) => config,
+            Err(err) => {
+                tracing::warn!(
+                    error = %err,
+                    profile_id,
+                    "failed to resolve selected permission profile"
+                );
+                self.chat_widget.add_error_message(format!(
+                    "Failed to set permission profile `{profile_id}`: {err}"
+                ));
+                return false;
+            }
+        };
+        let permission_profile = selected_config.permissions.permission_profile();
+        let active_permission_profile = selected_config.permissions.active_permission_profile();
+        let network = selected_config.permissions.network.clone();
+
+        let mut config = self.config.clone();
+        if let Some(policy) = approval_policy
+            && !self.try_set_approval_policy_on_config(
+                &mut config,
+                policy,
+                "Failed to set approval policy",
+                "failed to set selected permission profile approval policy on app config",
+            )
+        {
+            return false;
+        }
+        if let Err(err) = config
+            .permissions
+            .set_permission_profile_from_session_snapshot(
+                PermissionProfileSnapshot::from_session_snapshot(
+                    permission_profile.clone(),
+                    active_permission_profile.clone(),
+                ),
+            )
+        {
+            tracing::warn!(
+                error = %err,
+                profile_id,
+                "failed to set selected permission profile on app config"
+            );
+            self.chat_widget.add_error_message(format!(
+                "Failed to set permission profile `{profile_id}`: {err}"
+            ));
+            return false;
+        }
+        if let Some(reviewer) = approvals_reviewer {
+            config.approvals_reviewer = reviewer;
+        }
+        config.permissions.network = network.clone();
+        self.config = config;
+
+        if let Some(policy) = approval_policy {
+            self.runtime_approval_policy_override = Some(policy);
+            self.chat_widget.set_approval_policy(policy);
+        }
+        if let Err(err) = self.chat_widget.set_permission_profile_with_active_profile(
+            permission_profile.clone(),
+            active_permission_profile.clone(),
+        ) {
+            tracing::warn!(
+                error = %err,
+                profile_id,
+                "failed to set selected permission profile on chat config"
+            );
+            self.chat_widget.add_error_message(format!(
+                "Failed to set permission profile `{profile_id}`: {err}"
+            ));
+            return false;
+        }
+        if let Some(reviewer) = approvals_reviewer {
+            self.chat_widget.set_approvals_reviewer(reviewer);
+        }
+        self.chat_widget.set_permission_network(network);
+        self.runtime_permission_profile_override =
+            Some(RuntimePermissionProfileOverride::from_config(&self.config));
+        self.sync_active_thread_permission_settings_to_cached_session()
+            .await;
+        self.app_event_tx
+            .send(AppEvent::CodexOp(AppCommand::override_turn_context(
+                /*cwd*/ None,
+                approval_policy,
+                approvals_reviewer,
+                Some(permission_profile.clone()),
+                active_permission_profile,
+                /*windows_sandbox_level*/ None,
+                /*model*/ None,
+                /*effort*/ None,
+                /*summary*/ None,
+                /*service_tier*/ None,
+                /*collaboration_mode*/ None,
+                /*personality*/ None,
+            )));
+        self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new(
+            history_cell::new_info_event(
+                format!("Permissions updated to {display_label}"),
+                /*hint*/ None,
+            ),
+        )));
+        true
+    }
+
     pub(super) async fn refresh_in_memory_config_from_disk(&mut self) -> Result<()> {
         let mut config = self
             .rebuild_config_for_cwd(self.chat_widget.config_ref().cwd.to_path_buf())
@@ -73,13 +230,25 @@ impl App {
                 "Failed to carry forward approval policy override: {err}"
             ));
         }
-        if let Some(profile) = self.runtime_permission_profile_override.as_ref()
-            && let Err(err) = config.permissions.set_permission_profile(profile.clone())
-        {
-            tracing::warn!(%err, "failed to carry forward permission profile override");
-            self.chat_widget.add_error_message(format!(
-                "Failed to carry forward permission profile override: {err}"
-            ));
+        if let Some(profile_override) = self.runtime_permission_profile_override.as_ref() {
+            match config
+                .permissions
+                .set_permission_profile_from_session_snapshot(
+                    PermissionProfileSnapshot::from_session_snapshot(
+                        profile_override.permission_profile.clone(),
+                        profile_override.active_permission_profile.clone(),
+                    ),
+                ) {
+                Ok(()) => {
+                    config.permissions.network = profile_override.network.clone();
+                }
+                Err(err) => {
+                    tracing::warn!(%err, "failed to carry forward permission profile override");
+                    self.chat_widget.add_error_message(format!(
+                        "Failed to carry forward permission profile override: {err}"
+                    ));
+                }
+            }
         }
     }
 
@@ -341,8 +510,9 @@ impl App {
             self.chat_widget
                 .add_error_message(format!("Failed to enable Auto-review: {err}"));
         }
-        if let Some(permission_profile) = permission_profile_override_value {
-            self.runtime_permission_profile_override = Some(permission_profile);
+        if permission_profile_override.is_some() {
+            self.runtime_permission_profile_override =
+                Some(RuntimePermissionProfileOverride::from_config(&self.config));
         }
 
         if approval_policy_override.is_some()
diff --git a/codex-rs/tui/src/app/event_dispatch.rs b/codex-rs/tui/src/app/event_dispatch.rs
index 51615f6a956..cd6bd0b5c91 100644
--- a/codex-rs/tui/src/app/event_dispatch.rs
+++ b/codex-rs/tui/src/app/event_dispatch.rs
@@ -798,18 +798,24 @@ impl App {
             AppEvent::OpenFullAccessConfirmation {
                 preset,
                 return_to_permissions,
+                profile_selection,
             } => {
-                self.chat_widget
-                    .open_full_access_confirmation(preset, return_to_permissions);
+                self.chat_widget.open_full_access_confirmation(
+                    preset,
+                    return_to_permissions,
+                    profile_selection,
+                );
             }
             AppEvent::OpenWorldWritableWarningConfirmation {
                 preset,
+                profile_selection,
                 sample_paths,
                 extra_count,
                 failed_scan,
             } => {
                 self.chat_widget.open_world_writable_warning_confirmation(
                     preset,
+                    profile_selection,
                     sample_paths,
                     extra_count,
                     failed_scan,
@@ -846,10 +852,17 @@ impl App {
                     self.launch_external_editor(tui).await;
                 }
             }
-            AppEvent::OpenWindowsSandboxEnablePrompt { preset } => {
-                self.chat_widget.open_windows_sandbox_enable_prompt(preset);
+            AppEvent::OpenWindowsSandboxEnablePrompt {
+                preset,
+                profile_selection,
+            } => {
+                self.chat_widget
+                    .open_windows_sandbox_enable_prompt(preset, profile_selection);
             }
-            AppEvent::OpenWindowsSandboxFallbackPrompt { preset } => {
+            AppEvent::OpenWindowsSandboxFallbackPrompt {
+                preset,
+                profile_selection,
+            } => {
                 self.session_telemetry.counter(
                     "codex.windows_sandbox.fallback_prompt_shown",
                     /*inc*/ 1,
@@ -864,12 +877,30 @@ impl App {
                     );
                 }
                 self.chat_widget
-                    .open_windows_sandbox_fallback_prompt(preset);
+                    .open_windows_sandbox_fallback_prompt(preset, profile_selection);
             }
-            AppEvent::BeginWindowsSandboxElevatedSetup { preset } => {
+            AppEvent::BeginWindowsSandboxElevatedSetup {
+                preset,
+                profile_selection,
+            } => {
                 #[cfg(target_os = "windows")]
                 {
-                    let permission_profile = preset.permission_profile.clone();
+                    let permission_profile = match self
+                        .permission_profile_for_windows_setup(&preset, profile_selection.as_ref())
+                        .await
+                    {
+                        Ok(permission_profile) => permission_profile,
+                        Err(err) => {
+                            tracing::warn!(
+                                error = %err,
+                                "failed to resolve permission profile for elevated Windows sandbox setup"
+                            );
+                            self.chat_widget.add_error_message(format!(
+                                "Failed to prepare Windows sandbox for the selected permission profile: {err}"
+                            ));
+                            return Ok(AppRunControl::Continue);
+                        }
+                    };
                     let policy_cwd = self.config.cwd.clone();
                     let command_cwd = policy_cwd.clone();
                     let env_map: std::collections::HashMap<String, String> =
@@ -885,6 +916,7 @@ impl App {
                         tx.send(AppEvent::EnableWindowsSandboxForAgentMode {
                             preset,
                             mode: WindowsSandboxEnableMode::Elevated,
+                            profile_selection,
                         });
                         return Ok(AppRunControl::Continue);
                     }
@@ -901,7 +933,10 @@ impl App {
                             );
                         })
                     else {
-                        tx.send(AppEvent::OpenWindowsSandboxFallbackPrompt { preset });
+                        tx.send(AppEvent::OpenWindowsSandboxFallbackPrompt {
+                            preset,
+                            profile_selection,
+                        });
                         return Ok(AppRunControl::Continue);
                     };
                     tokio::task::spawn_blocking(move || {
@@ -922,6 +957,7 @@ impl App {
                                 AppEvent::EnableWindowsSandboxForAgentMode {
                                     preset: preset.clone(),
                                     mode: WindowsSandboxEnableMode::Elevated,
+                                    profile_selection: profile_selection.clone(),
                                 }
                             }
                             Err(err) => {
@@ -953,7 +989,10 @@ impl App {
                                     error = %err,
                                     "failed to run elevated Windows sandbox setup"
                                 );
-                                AppEvent::OpenWindowsSandboxFallbackPrompt { preset }
+                                AppEvent::OpenWindowsSandboxFallbackPrompt {
+                                    preset,
+                                    profile_selection,
+                                }
                             }
                         };
                         tx.send(event);
@@ -961,13 +1000,31 @@ impl App {
                 }
                 #[cfg(not(target_os = "windows"))]
                 {
-                    let _ = preset;
+                    let _ = (preset, profile_selection);
                 }
             }
-            AppEvent::BeginWindowsSandboxLegacySetup { preset } => {
+            AppEvent::BeginWindowsSandboxLegacySetup {
+                preset,
+                profile_selection,
+            } => {
                 #[cfg(target_os = "windows")]
                 {
-                    let permission_profile = preset.permission_profile.clone();
+                    let permission_profile = match self
+                        .permission_profile_for_windows_setup(&preset, profile_selection.as_ref())
+                        .await
+                    {
+                        Ok(permission_profile) => permission_profile,
+                        Err(err) => {
+                            tracing::warn!(
+                                error = %err,
+                                "failed to resolve permission profile for legacy Windows sandbox setup"
+                            );
+                            self.chat_widget.add_error_message(format!(
+                                "Failed to prepare Windows sandbox for the selected permission profile: {err}"
+                            ));
+                            return Ok(AppRunControl::Continue);
+                        }
+                    };
                     let policy_cwd = self.config.cwd.clone();
                     let command_cwd = policy_cwd.clone();
                     let env_map: std::collections::HashMap<String, String> =
@@ -986,7 +1043,10 @@ impl App {
                             );
                         })
                     else {
-                        tx.send(AppEvent::OpenWindowsSandboxFallbackPrompt { preset });
+                        tx.send(AppEvent::OpenWindowsSandboxFallbackPrompt {
+                            preset,
+                            profile_selection,
+                        });
                         return Ok(AppRunControl::Continue);
                     };
                     tokio::task::spawn_blocking(move || {
@@ -1012,12 +1072,13 @@ impl App {
                         tx.send(AppEvent::EnableWindowsSandboxForAgentMode {
                             preset,
                             mode: WindowsSandboxEnableMode::Legacy,
+                            profile_selection,
                         });
                     });
                 }
                 #[cfg(not(target_os = "windows"))]
                 {
-                    let _ = preset;
+                    let _ = (preset, profile_selection);
                 }
             }
             AppEvent::BeginWindowsSandboxGrantReadRoot { path } => {
@@ -1080,7 +1141,11 @@ impl App {
                         ));
                 }
             },
-            AppEvent::EnableWindowsSandboxForAgentMode { preset, mode } => {
+            AppEvent::EnableWindowsSandboxForAgentMode {
+                preset,
+                mode,
+                profile_selection,
+            } => {
                 #[cfg(target_os = "windows")]
                 {
                     self.chat_widget.clear_windows_sandbox_setup_status();
@@ -1140,11 +1205,40 @@ impl App {
                                 self.app_event_tx.send(
                                     AppEvent::OpenWorldWritableWarningConfirmation {
                                         preset: Some(preset.clone()),
+                                        profile_selection: profile_selection.clone(),
                                         sample_paths,
                                         extra_count,
                                         failed_scan,
                                     },
                                 );
+                            } else if let Some(selection) = profile_selection {
+                                self.app_event_tx.send(AppEvent::CodexOp(
+                                    AppCommand::override_turn_context(
+                                        /*cwd*/ None,
+                                        /*approval_policy*/ None,
+                                        /*approvals_reviewer*/ None,
+                                        /*permission_profile*/ None,
+                                        /*active_permission_profile*/ None,
+                                        #[cfg(target_os = "windows")]
+                                        Some(windows_sandbox_level),
+                                        /*model*/ None,
+                                        /*effort*/ None,
+                                        /*summary*/ None,
+                                        /*service_tier*/ None,
+                                        /*collaboration_mode*/ None,
+                                        /*personality*/ None,
+                                    ),
+                                ));
+                                self.apply_permission_profile_selection(selection).await;
+                                let _ = mode;
+                                self.chat_widget.add_plain_history_lines(vec![
+                                    Line::from(vec!["• ".dim(), "Sandbox ready".into()]),
+                                    Line::from(vec![
+                                        "  ".into(),
+                                        "Codex can now safely edit files and execute commands in your computer"
+                                            .dark_gray(),
+                                    ]),
+                                ]);
                             } else {
                                 self.app_event_tx.send(AppEvent::CodexOp(
                                     AppCommand::override_turn_context(
@@ -1194,7 +1288,7 @@ impl App {
                 }
                 #[cfg(not(target_os = "windows"))]
                 {
-                    let _ = (preset, mode);
+                    let _ = (preset, mode, profile_selection);
                 }
             }
             AppEvent::PersistModelSelection { model, effort } => {
@@ -1461,7 +1555,7 @@ impl App {
                     return Ok(AppRunControl::Continue);
                 }
                 self.runtime_permission_profile_override =
-                    Some(self.config.permissions.permission_profile().clone());
+                    Some(RuntimePermissionProfileOverride::from_config(&self.config));
                 self.sync_active_thread_permission_settings_to_cached_session()
                     .await;
 
@@ -1497,6 +1591,9 @@ impl App {
                     }
                 }
             }
+            AppEvent::SelectPermissionProfile(selection) => {
+                self.apply_permission_profile_selection(selection).await;
+            }
             AppEvent::UpdateApprovalsReviewer(policy) => {
                 self.config.approvals_reviewer = policy;
                 self.chat_widget.set_approvals_reviewer(policy);
diff --git a/codex-rs/tui/src/app/platform_actions.rs b/codex-rs/tui/src/app/platform_actions.rs
index 11289bc2aae..c87776f48b1 100644
--- a/codex-rs/tui/src/app/platform_actions.rs
+++ b/codex-rs/tui/src/app/platform_actions.rs
@@ -47,6 +47,7 @@ impl App {
 fn send_world_writable_scan_failed(tx: &AppEventSender) {
     tx.send(AppEvent::OpenWorldWritableWarningConfirmation {
         preset: None,
+        profile_selection: None,
         sample_paths: Vec::new(),
         extra_count: 0usize,
         failed_scan: true,
diff --git a/codex-rs/tui/src/app/tests.rs b/codex-rs/tui/src/app/tests.rs
index 92e824aec72..c0050db2858 100644
--- a/codex-rs/tui/src/app/tests.rs
+++ b/codex-rs/tui/src/app/tests.rs
@@ -80,6 +80,7 @@ use codex_protocol::config_types::CollaborationMode;
 use codex_protocol::config_types::CollaborationModeMask;
 use codex_protocol::config_types::ModeKind;
 use codex_protocol::config_types::Personality;
+use codex_protocol::config_types::SandboxMode;
 use codex_protocol::config_types::ServiceTier;
 use codex_protocol::config_types::Settings;
 use codex_protocol::models::ActivePermissionProfile;
@@ -1627,6 +1628,91 @@ async fn reset_memories_clears_local_memory_directories() -> Result<()> {
     .await
 }
 
+#[tokio::test]
+async fn apply_permission_profile_selection_preserves_loader_overrides() -> Result<()> {
+    let (mut app, mut app_event_rx, _op_rx) = make_test_app_with_channels().await;
+    let codex_home = tempdir()?;
+    let selected_config = codex_home.path().join("work.config.toml");
+    std::fs::write(
+        &selected_config,
+        r#"
+default_permissions = "locked-down"
+
+[permissions.locked-down.filesystem]
+":minimal" = "read"
+"#,
+    )?;
+    app.config.codex_home = codex_home.path().to_path_buf().abs();
+    app.loader_overrides.user_config_path = Some(selected_config.abs());
+    app.harness_overrides.sandbox_mode = Some(SandboxMode::WorkspaceWrite);
+    app.harness_overrides.permission_profile = Some(PermissionProfile::workspace_write());
+
+    assert!(
+        app.apply_permission_profile_selection(PermissionProfileSelection {
+            profile_id: "locked-down".to_string(),
+            approval_policy: None,
+            approvals_reviewer: None,
+            display_label: "locked-down".to_string(),
+        })
+        .await
+    );
+
+    assert_eq!(
+        app.config
+            .permissions
+            .active_permission_profile()
+            .as_ref()
+            .map(|profile| profile.id.as_str()),
+        Some("locked-down")
+    );
+    assert_eq!(
+        app.chat_widget
+            .config_ref()
+            .permissions
+            .active_permission_profile()
+            .as_ref()
+            .map(|profile| profile.id.as_str()),
+        Some("locked-down")
+    );
+    assert_eq!(
+        app.runtime_permission_profile_override,
+        Some(RuntimePermissionProfileOverride::from_config(&app.config))
+    );
+    let op = match app_event_rx.try_recv() {
+        Ok(AppEvent::CodexOp(op)) => op,
+        other => panic!("expected CodexOp event, got {other:?}"),
+    };
+    assert_eq!(
+        op,
+        Op::OverrideTurnContext {
+            cwd: None,
+            approval_policy: None,
+            approvals_reviewer: None,
+            permission_profile: Some(app.config.permissions.permission_profile().clone()),
+            active_permission_profile: app.config.permissions.active_permission_profile(),
+            windows_sandbox_level: None,
+            model: None,
+            effort: None,
+            summary: None,
+            service_tier: None,
+            collaboration_mode: None,
+            personality: None,
+        }
+    );
+    let cell = match app_event_rx.try_recv() {
+        Ok(AppEvent::InsertHistoryCell(cell)) => cell,
+        other => panic!("expected InsertHistoryCell event, got {other:?}"),
+    };
+    let rendered = cell
+        .display_lines(/*width*/ 120)
+        .into_iter()
+        .map(|line| line.to_string())
+        .collect::<Vec<_>>()
+        .join("\n");
+    assert!(rendered.contains("Permissions updated to locked-down"));
+    Ok(())
+}
+
 #[tokio::test]
 async fn update_feature_flags_enabling_guardian_selects_auto_review() -> Result<()> {
     let (mut app, mut app_event_rx, mut op_rx) = make_test_app_with_channels().await;
@@ -1687,7 +1773,7 @@ async fn update_feature_flags_enabling_guardian_selects_auto_review() -> Result<
     assert_eq!(app.runtime_approval_policy_override, None);
     assert_eq!(
         app.runtime_permission_profile_override,
-        Some(auto_review.permission_profile())
+        Some(RuntimePermissionProfileOverride::from_config(&app.config))
     );
     assert_eq!(
         op_rx.try_recv(),
diff --git a/codex-rs/tui/src/app/thread_routing.rs b/codex-rs/tui/src/app/thread_routing.rs
index 2c2baf512dd..8f15aed79a3 100644
--- a/codex-rs/tui/src/app/thread_routing.rs
+++ b/codex-rs/tui/src/app/thread_routing.rs
@@ -591,7 +591,9 @@ impl App {
                     let permissions_override = Self::turn_permissions_override_from_config(
                         config,
                         active_permission_profile.as_ref(),
-                        self.runtime_permission_profile_override.as_ref(),
+                        self.runtime_permission_profile_override
+                            .as_ref()
+                            .map(|profile| &profile.permission_profile),
                     );
                     app_server
                         .turn_start(
diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs
index a85ee5a70c9..17b749971a2 100644
--- a/codex-rs/tui/src/app_event.rs
+++ b/codex-rs/tui/src/app_event.rs
@@ -686,6 +686,7 @@ pub(crate) enum AppEvent {
     OpenFullAccessConfirmation {
         preset: ApprovalPreset,
         return_to_permissions: bool,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Open the Windows world-writable directories warning.
@@ -695,6 +696,7 @@ pub(crate) enum AppEvent {
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     OpenWorldWritableWarningConfirmation {
         preset: Option<ApprovalPreset>,
+        profile_selection: Option<PermissionProfileSelection>,
         /// Up to 3 sample world-writable directories to display in the warning.
         sample_paths: Vec<String>,
         /// If there are more than `sample_paths`, this carries the remaining count.
@@ -707,24 +709,28 @@ pub(crate) enum AppEvent {
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     OpenWindowsSandboxEnablePrompt {
         preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Open the Windows sandbox fallback prompt after declining or failing elevation.
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     OpenWindowsSandboxFallbackPrompt {
         preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Begin the elevated Windows sandbox setup flow.
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     BeginWindowsSandboxElevatedSetup {
         preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Begin the non-elevated Windows sandbox setup flow.
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     BeginWindowsSandboxLegacySetup {
         preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Begin a non-elevated grant of read access for an additional directory.
@@ -745,6 +751,7 @@ pub(crate) enum AppEvent {
     EnableWindowsSandboxForAgentMode {
         preset: ApprovalPreset,
         mode: WindowsSandboxEnableMode,
+        profile_selection: Option<PermissionProfileSelection>,
     },
 
     /// Update the Windows sandbox feature mode without changing approval presets.
@@ -756,6 +763,9 @@ pub(crate) enum AppEvent {
     /// Update the current built-in active permission profile in the running app and widget.
     UpdateActivePermissionProfile(ActivePermissionProfile),
 
+    /// Select a named permission profile, optionally applying built-in mode settings too.
+    SelectPermissionProfile(PermissionProfileSelection),
+
     /// Update the current approvals reviewer in the running app and widget.
     UpdateApprovalsReviewer(ApprovalsReviewer),
 
@@ -995,6 +1005,15 @@ pub(crate) enum AppEvent {
     },
 }
 
+/// Named profile selection to apply after any required UI guardrails complete.
+#[derive(Debug, Clone)]
+pub(crate) struct PermissionProfileSelection {
+    pub profile_id: String,
+    pub approval_policy: Option<AskForApproval>,
+    pub approvals_reviewer: Option<ApprovalsReviewer>,
+    pub display_label: String,
+}
+
 #[derive(Debug)]
 pub(crate) struct RealtimeWebrtcOffer {
     pub(crate) offer_sdp: String,
diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs
index 0ba974d88e4..1b24daac26c 100644
--- a/codex-rs/tui/src/chatwidget.rs
+++ b/codex-rs/tui/src/chatwidget.rs
@@ -256,6 +256,7 @@ fn queued_message_edit_hint_binding(
 
 use crate::app_event::AppEvent;
 use crate::app_event::ExitMode;
+use crate::app_event::PermissionProfileSelection;
 use crate::app_event::RateLimitRefreshOrigin;
 #[cfg(target_os = "windows")]
 use crate::app_event::WindowsSandboxEnableMode;
@@ -459,6 +460,7 @@ use unicode_segmentation::UnicodeSegmentation;
 
 const USER_SHELL_COMMAND_HELP_TITLE: &str = "Prefix a command with ! to run it locally";
 const USER_SHELL_COMMAND_HELP_HINT: &str = "Example: !ls";
+const AUTO_REVIEW_DESCRIPTION: &str = "Same workspace-write permissions as Default, but eligible `on-request` approvals are routed through the auto-reviewer subagent.";
 const DEFAULT_OPENAI_BASE_URL: &str = "https://api.openai.com/v1";
 const DEFAULT_STATUS_LINE_ITEMS: [&str; 2] = ["model-with-reasoning", "current-dir"];
 const MAX_AGENT_COPY_HISTORY: usize = 32;
diff --git a/codex-rs/tui/src/chatwidget/permission_popups.rs b/codex-rs/tui/src/chatwidget/permission_popups.rs
index dc5d6c1870d..d908cf67750 100644
--- a/codex-rs/tui/src/chatwidget/permission_popups.rs
+++ b/codex-rs/tui/src/chatwidget/permission_popups.rs
@@ -55,7 +55,6 @@ impl ChatWidget {
             } else {
                 preset.label.to_string()
             };
-            let preset_approval = AskForApproval::from(preset.approval);
             let base_description =
                 Some(preset.description.replace(" (Identical to Agent mode)", ""));
             let approval_disabled_reason = match self
@@ -70,86 +69,13 @@ impl ChatWidget {
             let default_disabled_reason = approval_disabled_reason
                 .clone()
                 .or_else(|| guardian_disabled_reason(false));
-            let requires_confirmation = preset.id == "full-access"
-                && !self
-                    .config
-                    .notices
-                    .hide_full_access_warning
-                    .unwrap_or(false);
-            let default_actions: Vec<SelectionAction> = if requires_confirmation {
-                let preset_clone = preset.clone();
-                vec![Box::new(move |tx| {
-                    tx.send(AppEvent::OpenFullAccessConfirmation {
-                        preset: preset_clone.clone(),
-                        return_to_permissions: !include_read_only,
-                    });
-                })]
-            } else if preset.id == "auto" {
-                #[cfg(target_os = "windows")]
-                {
-                    if WindowsSandboxLevel::from_config(&self.config)
-                        == WindowsSandboxLevel::Disabled
-                    {
-                        let preset_clone = preset.clone();
-                        if crate::legacy_core::windows_sandbox::ELEVATED_SANDBOX_NUX_ENABLED
-                            && crate::legacy_core::windows_sandbox::sandbox_setup_is_complete(
-                                self.config.codex_home.as_path(),
-                            )
-                        {
-                            vec![Box::new(move |tx| {
-                                tx.send(AppEvent::EnableWindowsSandboxForAgentMode {
-                                    preset: preset_clone.clone(),
-                                    mode: WindowsSandboxEnableMode::Elevated,
-                                });
-                            })]
-                        } else {
-                            vec![Box::new(move |tx| {
-                                tx.send(AppEvent::OpenWindowsSandboxEnablePrompt {
-                                    preset: preset_clone.clone(),
-                                });
-                            })]
-                        }
-                    } else if let Some((sample_paths, extra_count, failed_scan)) =
-                        self.world_writable_warning_details()
-                    {
-                        let preset_clone = preset.clone();
-                        vec![Box::new(move |tx| {
-                            tx.send(AppEvent::OpenWorldWritableWarningConfirmation {
-                                preset: Some(preset_clone.clone()),
-                                sample_paths: sample_paths.clone(),
-                                extra_count,
-                                failed_scan,
-                            });
-                        })]
-                    } else {
-                        Self::approval_preset_actions(
-                            preset_approval,
-                            preset.permission_profile.clone(),
-                            preset.active_permission_profile.clone(),
-                            base_name.clone(),
-                            ApprovalsReviewer::User,
-                        )
-                    }
-                }
-                #[cfg(not(target_os = "windows"))]
-                {
-                    Self::approval_preset_actions(
-                        preset_approval,
-                        preset.permission_profile.clone(),
-                        preset.active_permission_profile.clone(),
-                        base_name.clone(),
-                        ApprovalsReviewer::User,
-                    )
-                }
-            } else {
-                Self::approval_preset_actions(
-                    preset_approval,
-                    preset.permission_profile.clone(),
-                    preset.active_permission_profile.clone(),
-                    base_name.clone(),
-                    ApprovalsReviewer::User,
-                )
-            };
+            let default_actions = self.permission_mode_actions(
+                &preset,
+                base_name.clone(),
+                ApprovalsReviewer::User,
+                /*profile_selection*/ None,
+                /*return_to_permissions*/ !include_read_only,
+            );
             if preset.id == "auto" {
                 items.push(SelectionItem {
                     name: base_name.clone(),
@@ -170,10 +96,7 @@ impl ChatWidget {
                 if guardian_approval_enabled {
                     items.push(SelectionItem {
                         name: "Auto-review".to_string(),
-                        description: Some(
-                            "Same workspace-write permissions as Default, but eligible `on-request` approvals are routed through the auto-reviewer subagent."
-                                .to_string(),
-                        ),
+                        description: Some(AUTO_REVIEW_DESCRIPTION.to_string()),
                         is_current: current_review_policy == ApprovalsReviewer::AutoReview
                             && Self::preset_matches_current(
                                 current_approval,
@@ -181,12 +104,12 @@ impl ChatWidget {
                                 self.config.cwd.as_path(),
                                 &preset,
                             ),
-                        actions: Self::approval_preset_actions(
-                            preset_approval,
-                            preset.permission_profile.clone(),
-                            preset.active_permission_profile.clone(),
+                        actions: self.permission_mode_actions(
+                            &preset,
                             "Auto-review".to_string(),
                             ApprovalsReviewer::AutoReview,
+                            /*profile_selection*/ None,
+                            /*return_to_permissions*/ !include_read_only,
                         ),
                         dismiss_on_select: true,
                         disabled_reason: approval_disabled_reason
@@ -346,6 +269,97 @@ impl ChatWidget {
         })]
     }
 
+    pub(super) fn permission_profile_selection_actions(
+        selection: PermissionProfileSelection,
+    ) -> Vec<SelectionAction> {
+        vec![Box::new(move |tx| {
+            tx.send(AppEvent::SelectPermissionProfile(selection.clone()));
+        })]
+    }
+
+    pub(super) fn permission_mode_actions(
+        &self,
+        preset: &ApprovalPreset,
+        label: String,
+        approvals_reviewer: ApprovalsReviewer,
+        profile_selection: Option<PermissionProfileSelection>,
+        return_to_permissions: bool,
+    ) -> Vec<SelectionAction> {
+        let apply_actions = || {
+            profile_selection.clone().map_or_else(
+                || {
+                    Self::approval_preset_actions(
+                        AskForApproval::from(preset.approval),
+                        preset.permission_profile.clone(),
+                        preset.active_permission_profile.clone(),
+                        label.clone(),
+                        approvals_reviewer,
+                    )
+                },
+                Self::permission_profile_selection_actions,
+            )
+        };
+        let requires_confirmation = approvals_reviewer == ApprovalsReviewer::User
+            && preset.id == "full-access"
+            && !self
+                .config
+                .notices
+                .hide_full_access_warning
+                .unwrap_or(false);
+        if requires_confirmation {
+            let preset = preset.clone();
+            return vec![Box::new(move |tx| {
+                tx.send(AppEvent::OpenFullAccessConfirmation {
+                    preset: preset.clone(),
+                    return_to_permissions,
+                    profile_selection: profile_selection.clone(),
+                });
+            })];
+        }
+        if approvals_reviewer == ApprovalsReviewer::User && preset.id == "auto" {
+            #[cfg(target_os = "windows")]
+            {
+                if WindowsSandboxLevel::from_config(&self.config) == WindowsSandboxLevel::Disabled {
+                    let preset = preset.clone();
+                    if crate::legacy_core::windows_sandbox::ELEVATED_SANDBOX_NUX_ENABLED
+                        && crate::legacy_core::windows_sandbox::sandbox_setup_is_complete(
+                            self.config.codex_home.as_path(),
+                        )
+                    {
+                        return vec![Box::new(move |tx| {
+                            tx.send(AppEvent::EnableWindowsSandboxForAgentMode {
+                                preset: preset.clone(),
+                                mode: WindowsSandboxEnableMode::Elevated,
+                                profile_selection: profile_selection.clone(),
+                            });
+                        })];
+                    }
+                    return vec![Box::new(move |tx| {
+                        tx.send(AppEvent::OpenWindowsSandboxEnablePrompt {
+                            preset: preset.clone(),
+                            profile_selection: profile_selection.clone(),
+                        });
+                    })];
+                }
+                if let Some((sample_paths, extra_count, failed_scan)) =
+                    self.world_writable_warning_details()
+                {
+                    let preset = preset.clone();
+                    return vec![Box::new(move |tx| {
+                        tx.send(AppEvent::OpenWorldWritableWarningConfirmation {
+                            preset: Some(preset.clone()),
+                            profile_selection: profile_selection.clone(),
+                            sample_paths: sample_paths.clone(),
+                            extra_count,
+                            failed_scan,
+                        });
+                    })];
+                }
+            }
+        }
+        apply_actions()
+    }
+
     pub(super) fn preset_matches_current(
         current_approval: AskForApproval,
         current_permission_profile: &PermissionProfile,
@@ -389,6 +403,7 @@ impl ChatWidget {
         &mut self,
         preset: ApprovalPreset,
         return_to_permissions: bool,
+        profile_selection: Option<PermissionProfileSelection>,
     ) {
         let selected_name = preset.label.to_string();
         let approval = AskForApproval::from(preset.approval);
@@ -406,23 +421,33 @@ impl ChatWidget {
         ));
         let header = ColumnRenderable::with(header_children);
 
-        let mut accept_actions = Self::approval_preset_actions(
-            approval,
-            preset.permission_profile.clone(),
-            preset.active_permission_profile.clone(),
-            selected_name.clone(),
-            ApprovalsReviewer::User,
+        let mut accept_actions = profile_selection.clone().map_or_else(
+            || {
+                Self::approval_preset_actions(
+                    approval,
+                    preset.permission_profile.clone(),
+                    preset.active_permission_profile.clone(),
+                    selected_name.clone(),
+                    ApprovalsReviewer::User,
+                )
+            },
+            Self::permission_profile_selection_actions,
         );
         accept_actions.push(Box::new(|tx| {
             tx.send(AppEvent::UpdateFullAccessWarningAcknowledged(true));
         }));
 
-        let mut accept_and_remember_actions = Self::approval_preset_actions(
-            approval,
-            preset.permission_profile,
-            preset.active_permission_profile,
-            selected_name,
-            ApprovalsReviewer::User,
+        let mut accept_and_remember_actions = profile_selection.map_or_else(
+            || {
+                Self::approval_preset_actions(
+                    approval,
+                    preset.permission_profile,
+                    preset.active_permission_profile,
+                    selected_name,
+                    ApprovalsReviewer::User,
+                )
+            },
+            Self::permission_profile_selection_actions,
         );
         accept_and_remember_actions.push(Box::new(|tx| {
             tx.send(AppEvent::UpdateFullAccessWarningAcknowledged(true));
diff --git a/codex-rs/tui/src/chatwidget/settings.rs b/codex-rs/tui/src/chatwidget/settings.rs
index 0df36f6bf89..eb3fc4eefd9 100644
--- a/codex-rs/tui/src/chatwidget/settings.rs
+++ b/codex-rs/tui/src/chatwidget/settings.rs
@@ -30,6 +30,30 @@ impl ChatWidget {
         Ok(())
     }
 
+    pub(crate) fn set_permission_profile_with_active_profile(
+        &mut self,
+        profile: PermissionProfile,
+        active_permission_profile: Option<ActivePermissionProfile>,
+    ) -> ConstraintResult<()> {
+        self.config
+            .permissions
+            .set_permission_profile_from_session_snapshot(
+                PermissionProfileSnapshot::from_session_snapshot(
+                    profile,
+                    active_permission_profile,
+                ),
+            )?;
+        self.refresh_status_surfaces();
+        Ok(())
+    }
+
+    pub(crate) fn set_permission_network(
+        &mut self,
+        network: Option<crate::legacy_core::config::NetworkProxySpec>,
+    ) {
+        self.config.permissions.network = network;
+    }
+
     #[cfg_attr(not(target_os = "windows"), allow(dead_code))]
     pub(crate) fn set_windows_sandbox_mode(&mut self, mode: Option<WindowsSandboxModeToml>) {
         self.config.permissions.windows_sandbox_mode = mode;
diff --git a/codex-rs/tui/src/chatwidget/slash_dispatch.rs b/codex-rs/tui/src/chatwidget/slash_dispatch.rs
index aa9e5112f80..b479718304e 100644
--- a/codex-rs/tui/src/chatwidget/slash_dispatch.rs
+++ b/codex-rs/tui/src/chatwidget/slash_dispatch.rs
@@ -297,7 +297,10 @@ impl ChatWidget {
                         &[],
                     );
                     self.app_event_tx
-                        .send(AppEvent::BeginWindowsSandboxElevatedSetup { preset });
+                        .send(AppEvent::BeginWindowsSandboxElevatedSetup {
+                            preset,
+                            profile_selection: None,
+                        });
                 }
                 #[cfg(not(target_os = "windows"))]
                 {
diff --git a/codex-rs/tui/src/chatwidget/tests/permissions.rs b/codex-rs/tui/src/chatwidget/tests/permissions.rs
index ae58271dff3..df59db17cbf 100644
--- a/codex-rs/tui/src/chatwidget/tests/permissions.rs
+++ b/codex-rs/tui/src/chatwidget/tests/permissions.rs
@@ -166,7 +166,9 @@ async fn full_access_confirmation_popup_snapshot() {
         .into_iter()
         .find(|preset| preset.id == "full-access")
         .expect("full access preset");
-    chat.open_full_access_confirmation(preset, /*return_to_permissions*/ false);
+    chat.open_full_access_confirmation(
+        preset, /*return_to_permissions*/ false, /*profile_selection*/ None,
+    );
 
     let popup = render_bottom_popup(&chat, /*width*/ 80);
     assert_chatwidget_snapshot!("full_access_confirmation_popup", popup);
@@ -181,7 +183,7 @@ async fn windows_auto_mode_prompt_requests_enabling_sandbox_feature() {
         .into_iter()
         .find(|preset| preset.id == "auto")
         .expect("auto preset");
-    chat.open_windows_sandbox_enable_prompt(preset);
+    chat.open_windows_sandbox_enable_prompt(preset, /*profile_selection*/ None);
 
     let popup = render_bottom_popup(&chat, /*width*/ 120);
     assert!(
@@ -799,8 +801,9 @@ async fn permissions_full_access_history_cell_emitted_only_after_confirmation()
             AppEvent::OpenFullAccessConfirmation {
                 preset,
                 return_to_permissions,
+                profile_selection,
             } => {
-                open_confirmation_event = Some((preset, return_to_permissions));
+                open_confirmation_event = Some((preset, return_to_permissions, profile_selection));
             }
             _ => {}
         }
@@ -811,9 +814,9 @@ async fn permissions_full_access_history_cell_emitted_only_after_confirmation()
             "did not expect history cell before confirming full access"
         );
     }
-    let (preset, return_to_permissions) =
+    let (preset, return_to_permissions, profile_selection) =
         open_confirmation_event.expect("expected full access confirmation event");
-    chat.open_full_access_confirmation(preset, return_to_permissions);
+    chat.open_full_access_confirmation(preset, return_to_permissions, profile_selection);
 
     let popup = render_bottom_popup(&chat, /*width*/ 80);
     assert!(
diff --git a/codex-rs/tui/src/chatwidget/windows_sandbox_prompts.rs b/codex-rs/tui/src/chatwidget/windows_sandbox_prompts.rs
index 3b71d467bf2..dd90af0557b 100644
--- a/codex-rs/tui/src/chatwidget/windows_sandbox_prompts.rs
+++ b/codex-rs/tui/src/chatwidget/windows_sandbox_prompts.rs
@@ -38,6 +38,7 @@ impl ChatWidget {
     pub(crate) fn open_world_writable_warning_confirmation(
         &mut self,
         preset: Option<ApprovalPreset>,
+        profile_selection: Option<PermissionProfileSelection>,
         sample_paths: Vec<String>,
         extra_count: usize,
         failed_scan: bool,
@@ -111,7 +112,9 @@ impl ChatWidget {
                 tx.send(AppEvent::SkipNextWorldWritableScan);
             }));
         }
-        if let (Some(approval), Some(permission_profile), Some(active_permission_profile)) = (
+        if let Some(selection) = profile_selection.clone() {
+            accept_actions.extend(Self::permission_profile_selection_actions(selection));
+        } else if let (Some(approval), Some(permission_profile), Some(active_permission_profile)) = (
             approval,
             permission_profile.clone(),
             active_permission_profile.clone(),
@@ -130,7 +133,10 @@ impl ChatWidget {
             tx.send(AppEvent::UpdateWorldWritableWarningAcknowledged(true));
             tx.send(AppEvent::PersistWorldWritableWarningAcknowledged);
         }));
-        if let (Some(approval), Some(permission_profile), Some(active_permission_profile)) =
+        if let Some(selection) = profile_selection {
+            accept_and_remember_actions
+                .extend(Self::permission_profile_selection_actions(selection));
+        } else if let (Some(approval), Some(permission_profile), Some(active_permission_profile)) =
             (approval, permission_profile, active_permission_profile)
         {
             accept_and_remember_actions.extend(Self::approval_preset_actions(
@@ -171,6 +177,7 @@ impl ChatWidget {
     pub(crate) fn open_world_writable_warning_confirmation(
         &mut self,
         _preset: Option<ApprovalPreset>,
+        _profile_selection: Option<PermissionProfileSelection>,
         _sample_paths: Vec<String>,
         _extra_count: usize,
         _failed_scan: bool,
@@ -178,7 +185,11 @@ impl ChatWidget {
     }
 
     #[cfg(target_os = "windows")]
-    pub(crate) fn open_windows_sandbox_enable_prompt(&mut self, preset: ApprovalPreset) {
+    pub(crate) fn open_windows_sandbox_enable_prompt(
+        &mut self,
+        preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
+    ) {
         use ratatui_macros::line;
 
         if !crate::legacy_core::windows_sandbox::ELEVATED_SANDBOX_NUX_ENABLED {
@@ -202,6 +213,7 @@ impl ChatWidget {
                         tx.send(AppEvent::EnableWindowsSandboxForAgentMode {
                             preset: preset_clone.clone(),
                             mode: WindowsSandboxEnableMode::Legacy,
+                            profile_selection: profile_selection.clone(),
                         });
                     })],
                     dismiss_on_select: true,
@@ -245,6 +257,7 @@ impl ChatWidget {
         let accept_otel = self.session_telemetry.clone();
         let legacy_otel = self.session_telemetry.clone();
         let legacy_preset = preset.clone();
+        let legacy_profile_selection = profile_selection.clone();
         let quit_otel = self.session_telemetry.clone();
         let items = vec![
             SelectionItem {
@@ -258,6 +271,7 @@ impl ChatWidget {
                     );
                     tx.send(AppEvent::BeginWindowsSandboxElevatedSetup {
                         preset: preset.clone(),
+                        profile_selection: profile_selection.clone(),
                     });
                 })],
                 dismiss_on_select: true,
@@ -274,6 +288,7 @@ impl ChatWidget {
                     );
                     tx.send(AppEvent::BeginWindowsSandboxLegacySetup {
                         preset: legacy_preset.clone(),
+                        profile_selection: legacy_profile_selection.clone(),
                     });
                 })],
                 dismiss_on_select: true,
@@ -305,10 +320,19 @@ impl ChatWidget {
     }
 
     #[cfg(not(target_os = "windows"))]
-    pub(crate) fn open_windows_sandbox_enable_prompt(&mut self, _preset: ApprovalPreset) {}
+    pub(crate) fn open_windows_sandbox_enable_prompt(
+        &mut self,
+        _preset: ApprovalPreset,
+        _profile_selection: Option<PermissionProfileSelection>,
+    ) {
+    }
 
     #[cfg(target_os = "windows")]
-    pub(crate) fn open_windows_sandbox_fallback_prompt(&mut self, preset: ApprovalPreset) {
+    pub(crate) fn open_windows_sandbox_fallback_prompt(
+        &mut self,
+        preset: ApprovalPreset,
+        profile_selection: Option<PermissionProfileSelection>,
+    ) {
         use ratatui_macros::line;
 
         let mut lines = Vec::new();
@@ -328,6 +352,8 @@ impl ChatWidget {
 
         let elevated_preset = preset.clone();
         let legacy_preset = preset;
+        let elevated_profile_selection = profile_selection.clone();
+        let legacy_profile_selection = profile_selection;
         let quit_otel = self.session_telemetry.clone();
         let items = vec![
             SelectionItem {
@@ -344,6 +370,7 @@ impl ChatWidget {
                         );
                         tx.send(AppEvent::BeginWindowsSandboxElevatedSetup {
                             preset: preset.clone(),
+                            profile_selection: elevated_profile_selection.clone(),
                         });
                     }
                 })],
@@ -364,6 +391,7 @@ impl ChatWidget {
                         );
                         tx.send(AppEvent::BeginWindowsSandboxLegacySetup {
                             preset: preset.clone(),
+                            profile_selection: legacy_profile_selection.clone(),
                         });
                     }
                 })],
@@ -396,7 +424,12 @@ impl ChatWidget {
     }
 
     #[cfg(not(target_os = "windows"))]
-    pub(crate) fn open_windows_sandbox_fallback_prompt(&mut self, _preset: ApprovalPreset) {}
+    pub(crate) fn open_windows_sandbox_fallback_prompt(
+        &mut self,
+        _preset: ApprovalPreset,
+        _profile_selection: Option<PermissionProfileSelection>,
+    ) {
+    }
 
     #[cfg(target_os = "windows")]
     pub(crate) fn maybe_prompt_windows_sandbox_enable(&mut self, show_now: bool) {
@@ -406,7 +439,7 @@ impl ChatWidget {
                 .into_iter()
                 .find(|preset| preset.id == "auto")
         {
-            self.open_windows_sandbox_enable_prompt(preset);
+            self.open_windows_sandbox_enable_prompt(preset, /*profile_selection*/ None);
         }
     }
 
