Add telemetry for the Windows system config namespace (#44284)

## What changed

Probe the default Windows system config namespace at session start and record `codex.windows_system_config.namespace_squatting_probe` once per process when metrics are available.

When `config.toml` or `requirements.toml` exists, check the containing directories for expected ownership and broad standard-user mutation allow ACEs, including permissions inherited by child files. Report coarse results for missing files, expected directories, unexpected types or owners, mutation permissions, and check errors.

The probe is observational: it does not change configuration loading or enforce a trust decision.

GitOrigin-RevId: e1c79dca5548e16e83c7b84b44ab0de4e2643d0d
This commit is contained in:
iceweasel-oai
2026-09-09 19:31:12 +00:00
committed by copyberry
parent c1840dc55e
commit bb71d758cd
11 changed files with 254 additions and 2 deletions
+1
View File
@@ -55,6 +55,7 @@ libc = { workspace = true }
core-foundation = "0.9"
[target.'cfg(target_os = "windows")'.dependencies]
codex-windows-sandbox = { workspace = true }
winapi-util = { workspace = true }
windows-sys = { version = "0.52", features = [
"Win32_Foundation",
+6
View File
@@ -5,6 +5,8 @@ mod macos;
mod project_discovery;
#[cfg(test)]
mod tests;
#[cfg(windows)]
mod windows;
use self::layer_io::LoadedConfigLayers;
use crate::CONFIG_TOML_FILE;
@@ -58,6 +60,10 @@ pub use local::LocalConfigLayers;
pub use local::LocalTomlLayer;
pub use local::LocalTomlLayerStack;
pub use local::load_local_config_layers;
#[cfg(windows)]
pub use windows::WindowsSystemConfigNamespaceProbe;
#[cfg(windows)]
pub use windows::probe_windows_system_config_namespace;
#[cfg(unix)]
const SYSTEM_CONFIG_TOML_FILE_UNIX: &str = "/etc/codex/config.toml";
+68
View File
@@ -0,0 +1,68 @@
use super::windows_codex_system_dir;
use std::path::Path;
/// Coarse compatibility result for the default Windows system-config namespace.
#[derive(Clone, Copy)]
pub enum WindowsSystemConfigNamespaceProbe {
Missing,
Expected,
UnexpectedType,
UnexpectedOwner,
StandardUserMutationAcl,
CheckError,
}
/// Observes the common user-preclaimed-directory shape without changing config loading.
/// This is not a trust decision: it only checks directory owner and broad
/// standard-user mutation ACLs.
pub fn probe_windows_system_config_namespace() -> WindowsSystemConfigNamespaceProbe {
let codex_dir = windows_codex_system_dir();
let has_system_file = match (
codex_dir.join("config.toml").try_exists(),
codex_dir.join("requirements.toml").try_exists(),
) {
(Ok(true), _) | (_, Ok(true)) => true,
(Ok(false), Ok(false)) => false,
_ => return WindowsSystemConfigNamespaceProbe::CheckError,
};
if !has_system_file {
return WindowsSystemConfigNamespaceProbe::Missing;
}
let Some(openai_dir) = codex_dir.parent() else {
return WindowsSystemConfigNamespaceProbe::CheckError;
};
let result = probe_directory(
openai_dir,
codex_windows_sandbox::path_has_standard_user_mutation_allow,
);
if !matches!(result, WindowsSystemConfigNamespaceProbe::Expected) {
return result;
}
let result = probe_directory(
codex_dir.as_path(),
codex_windows_sandbox::path_or_child_file_has_standard_user_mutation_allow,
);
if !matches!(result, WindowsSystemConfigNamespaceProbe::Expected) {
return result;
}
WindowsSystemConfigNamespaceProbe::Expected
}
fn probe_directory(
path: &Path,
mutation_allow: fn(&Path) -> anyhow::Result<bool>,
) -> WindowsSystemConfigNamespaceProbe {
if !path.is_dir() {
return WindowsSystemConfigNamespaceProbe::UnexpectedType;
}
match codex_windows_sandbox::path_has_trusted_system_owner(path) {
Ok(true) => {}
Ok(false) => return WindowsSystemConfigNamespaceProbe::UnexpectedOwner,
Err(_) => return WindowsSystemConfigNamespaceProbe::CheckError,
}
match mutation_allow(path) {
Ok(false) => WindowsSystemConfigNamespaceProbe::Expected,
Ok(true) => WindowsSystemConfigNamespaceProbe::StandardUserMutationAcl,
Err(_) => WindowsSystemConfigNamespaceProbe::CheckError,
}
}