mirror of
https://github.com/openai/codex.git
synced 2026-11-12 21:20:34 +00:00
## Why Automatic startup work and `codex doctor` can run before a workspace is trusted. A repository-controlled `PATH` must not be able to make those flows execute workspace-provided helpers. ## What changed - Resolve helpers used by automatic startup from trusted system installation directories, and give plugin-sync Git subprocesses a sanitized environment. - Make terminal detection environment-only and have doctor inspect executable locations without running them. Fetch update metadata with the HTTP client instead of `curl`. - Fall back conservatively when trusted terminal helpers are unavailable, including for tmux keyboard enhancement flags. ## Testing Add black-box coverage with hostile workspace `PATH` entries for startup, interactive tmux startup, support log collection, doctor, and curated plugin sync. Add unit coverage for trusted executable resolution and bounded update HTTP responses. GitOrigin-RevId: 3b8995eb422b60ed53b0386951de59e8f9bfc542
146 lines
5.2 KiB
Rust
146 lines
5.2 KiB
Rust
//! Captures how this Codex process was launched.
|
|
//!
|
|
//! Runtime diagnostics answer provenance questions that are hard to infer from
|
|
//! user reports: which binary is running, which install channel it resembles,
|
|
//! which platform it targets, and whether the search command comes from bundled
|
|
//! package files or from PATH.
|
|
|
|
use std::env;
|
|
|
|
use codex_install_context::InstallContext;
|
|
use codex_install_context::InstallMethod;
|
|
|
|
use super::CheckStatus;
|
|
use super::DoctorCheck;
|
|
use super::describe_install_context;
|
|
use super::doctor_install_context;
|
|
use super::push_path_detail;
|
|
|
|
/// Builds the process provenance row for the current Codex executable.
|
|
///
|
|
/// This check is informational and should not fail on its own; inconsistent
|
|
/// install state is reported by the installation and update checks instead.
|
|
pub(super) fn runtime_check() -> DoctorCheck {
|
|
let current_exe = env::current_exe().ok();
|
|
let install_context = doctor_install_context(current_exe.as_deref());
|
|
let os = env::consts::OS;
|
|
let arch = env::consts::ARCH;
|
|
let platform = format!("{os}-{arch}");
|
|
let install_method = install_method_name(&install_context);
|
|
let mut details = vec![
|
|
format!("version: {}", env!("CARGO_PKG_VERSION")),
|
|
format!("platform: {platform}"),
|
|
format!(
|
|
"install method: {}",
|
|
describe_install_context(&install_context)
|
|
),
|
|
format!("commit: {}", build_commit()),
|
|
];
|
|
push_path_detail(&mut details, "current executable", current_exe.as_deref());
|
|
|
|
DoctorCheck::new(
|
|
"runtime.provenance",
|
|
"runtime",
|
|
CheckStatus::Ok,
|
|
format!("running {install_method} on {platform}"),
|
|
)
|
|
.details(details)
|
|
}
|
|
|
|
/// Inspects the search command selected by the install context without executing it.
|
|
///
|
|
/// Package-layout installs should point at a bundled ripgrep binary, while local
|
|
/// installs without that layout usually resolve rg from PATH. A warning here
|
|
/// means features that depend on file search may degrade even when the CLI
|
|
/// launches.
|
|
pub(super) fn search_check() -> DoctorCheck {
|
|
let current_exe = env::current_exe().ok();
|
|
let install_context = doctor_install_context(current_exe.as_deref());
|
|
let rg_command = install_context.rg_command();
|
|
let provider = search_provider(&install_context);
|
|
let mut details = vec![
|
|
format!("search command: {}", rg_command.display()),
|
|
format!("search provider: {provider}"),
|
|
];
|
|
|
|
let status = if rg_command.components().count() > 1 {
|
|
match std::fs::metadata(&rg_command) {
|
|
Ok(metadata) if metadata.is_file() => {
|
|
details.push("search command readiness: file exists".to_string());
|
|
CheckStatus::Ok
|
|
}
|
|
Ok(_) => {
|
|
details.push("search command readiness: path is not a file".to_string());
|
|
CheckStatus::Warning
|
|
}
|
|
Err(err) => {
|
|
details.push(format!("search command readiness: {err}"));
|
|
CheckStatus::Warning
|
|
}
|
|
}
|
|
} else {
|
|
match which::which(&rg_command) {
|
|
Ok(path) => {
|
|
details.push(format!("search command path: {}", path.display()));
|
|
details.push("search command readiness: found; execution not verified".to_string());
|
|
CheckStatus::Ok
|
|
}
|
|
Err(err) => {
|
|
details.push(format!("search command readiness: {err}"));
|
|
CheckStatus::Warning
|
|
}
|
|
}
|
|
};
|
|
|
|
let summary = match status {
|
|
CheckStatus::Ok => format!("search command found ({provider}); execution not verified"),
|
|
CheckStatus::Warning => "search command could not be verified".to_string(),
|
|
CheckStatus::Fail => unreachable!(),
|
|
};
|
|
let mut check = DoctorCheck::new("runtime.search", "search", status, summary).details(details);
|
|
if status != CheckStatus::Ok {
|
|
check = check.remediation("Install ripgrep or repair the bundled Codex package.");
|
|
}
|
|
check
|
|
}
|
|
|
|
fn install_method_name(context: &InstallContext) -> &'static str {
|
|
match &context.method {
|
|
InstallMethod::Standalone { .. } => "standalone",
|
|
InstallMethod::Npm => "npm",
|
|
InstallMethod::Bun => "bun",
|
|
InstallMethod::VitePlus => "vite+",
|
|
InstallMethod::Pnpm => "pnpm",
|
|
InstallMethod::Brew => "brew",
|
|
InstallMethod::Other => "local build",
|
|
}
|
|
}
|
|
|
|
fn search_provider(context: &InstallContext) -> &'static str {
|
|
let rg_command = context.rg_command();
|
|
let from_package_layout = context
|
|
.package_layout
|
|
.as_ref()
|
|
.and_then(|package_layout| package_layout.path_dir.as_ref())
|
|
.is_some_and(|path_dir| rg_command.starts_with(path_dir));
|
|
let from_legacy_standalone = matches!(
|
|
&context.method,
|
|
InstallMethod::Standalone {
|
|
resources_dir: Some(resources_dir),
|
|
..
|
|
} if rg_command.starts_with(resources_dir)
|
|
);
|
|
|
|
if from_package_layout || from_legacy_standalone {
|
|
"bundled"
|
|
} else {
|
|
"system"
|
|
}
|
|
}
|
|
|
|
fn build_commit() -> &'static str {
|
|
option_env!("CODEX_BUILD_COMMIT")
|
|
.or(option_env!("GIT_COMMIT"))
|
|
.unwrap_or("unknown")
|
|
}
|