From 27541e9ef8ef4587a851ef6b1337e3223428f05f Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 15 Jun 2026 05:19:51 +0000 Subject: [PATCH] verify installed Codex app before launch --- codex-rs/cli/src/desktop_app/mac.rs | 18 ++++++++++++++++-- codex-rs/desktop-distribution/src/lib.rs | 10 ++++++++++ codex-rs/desktop-distribution/src/macos.rs | 11 +++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/codex-rs/cli/src/desktop_app/mac.rs b/codex-rs/cli/src/desktop_app/mac.rs index 7ed7d32c42..c5437ee854 100644 --- a/codex-rs/cli/src/desktop_app/mac.rs +++ b/codex-rs/cli/src/desktop_app/mac.rs @@ -1,5 +1,6 @@ use anyhow::Context as _; use codex_desktop_distribution::discover_installed_distribution; +use codex_desktop_distribution::validate_installed_distribution_at; use std::ffi::CString; use std::path::Path; use std::path::PathBuf; @@ -154,11 +155,11 @@ async fn install_codex_app_bundle(app_in_volume: &Path) -> anyhow::Result return Ok(dest_app), + Ok(()) => return validate_installed_codex_app(dest_app).await, Err(err) => { eprintln!( "warning: failed to install Codex.app to {applications_dir}: {err}", @@ -171,6 +172,19 @@ async fn install_codex_app_bundle(app_in_volume: &Path) -> anyhow::Result anyhow::Result { + let candidate = app_path.clone(); + let distribution = + tokio::task::spawn_blocking(move || validate_installed_distribution_at(candidate)) + .await + .context("Desktop validation task failed")??; + let app_path_display = app_path.display(); + let distribution = distribution.with_context(|| { + format!("refusing to launch unverified Codex Desktop at {app_path_display}") + })?; + Ok(distribution.app_root().to_path_buf()) +} + fn candidate_applications_dirs() -> anyhow::Result> { let mut dirs = vec![PathBuf::from("/Applications")]; dirs.push(user_applications_dir()?); diff --git a/codex-rs/desktop-distribution/src/lib.rs b/codex-rs/desktop-distribution/src/lib.rs index dc895cf7cd..87adceaa3c 100644 --- a/codex-rs/desktop-distribution/src/lib.rs +++ b/codex-rs/desktop-distribution/src/lib.rs @@ -120,6 +120,16 @@ pub fn discover_installed_distribution() platform::discover() } +/// Validates a macOS Codex app bundle at a known path using the same identity and containment +/// checks as installed-app discovery. Returns `Ok(None)` when the path is not a trusted Codex +/// Desktop distribution. +#[cfg(target_os = "macos")] +pub fn validate_installed_distribution_at( + app_root: impl AsRef, +) -> Result, DesktopDistributionError> { + platform::validate_candidate(app_root.as_ref()) +} + #[derive(Clone, Copy)] enum ResourceKind { Directory, diff --git a/codex-rs/desktop-distribution/src/macos.rs b/codex-rs/desktop-distribution/src/macos.rs index b4ec715eb8..a47b35899b 100644 --- a/codex-rs/desktop-distribution/src/macos.rs +++ b/codex-rs/desktop-distribution/src/macos.rs @@ -1,3 +1,4 @@ +use std::path::Path; use std::path::PathBuf; use std::process::Command; @@ -18,12 +19,18 @@ pub(crate) fn discover() -> Result, DesktopDistribution return Ok(None); } let app_root = PathBuf::from(String::from_utf8_lossy(&output.stdout).trim()); + validate_candidate(&app_root) +} + +pub(crate) fn validate_candidate( + app_root: &Path, +) -> Result, DesktopDistributionError> { let resources_root = app_root.join("Contents/Resources"); if app_root.extension().is_some_and(|value| value == "app") && resources_root.is_dir() - && has_openai_signature(&app_root)? + && has_openai_signature(app_root)? { - return InstalledDesktop::from_paths(app_root, resources_root).map(Some); + return InstalledDesktop::from_paths(app_root.to_path_buf(), resources_root).map(Some); } Ok(None) }