From 95cc6d7aac528ec53e1cce546de6f72649786c88 Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Sat, 2 May 2026 11:39:11 -0700 Subject: [PATCH] Fix hook trust test setup --- codex-rs/core/src/session/tests.rs | 53 +++++++++++++++---- .../runtimes/shell/unix_escalation_tests.rs | 28 +++++++++- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 5f791ff887..8e850bc47a 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -1171,15 +1171,17 @@ async fn reload_user_config_layer_refreshes_hooks() -> anyhow::Result<()> { .await?; let codex_home = session.codex_home().await; std::fs::create_dir_all(&codex_home)?; - std::fs::write( - codex_home.join(CONFIG_TOML_FILE), - r#" -[hooks] - -[[hooks.SessionStart]] -hooks = [{ type = "command", command = "python3 /tmp/user.py" }] -"#, - )?; + let config_toml_path = AbsolutePathBuf::try_from(codex_home.join(CONFIG_TOML_FILE))?; + let user_config: codex_config::TomlValue = serde_json::from_value(serde_json::json!({ + "hooks": { + "SessionStart": [{ + "hooks": [{ + "type": "command", + "command": "python3 /tmp/user.py", + }], + }], + }, + }))?; let request = codex_hooks::SessionStartRequest { session_id: session.conversation_id, @@ -1191,6 +1193,39 @@ hooks = [{ type = "command", command = "python3 /tmp/user.py" }] }; assert!(session.hooks().preview_session_start(&request).is_empty()); + let config = session.get_config().await; + let hook_list = codex_hooks::list_hooks(codex_hooks::HooksConfig { + feature_enabled: true, + config_layer_stack: Some( + config + .config_layer_stack + .with_user_config(&config_toml_path, user_config.clone()), + ), + ..codex_hooks::HooksConfig::default() + }); + assert_eq!(hook_list.hooks.len(), 1); + assert_eq!( + hook_list.hooks[0].trust_status, + codex_protocol::protocol::HookTrustStatus::Untrusted + ); + + let trusted_user_config: codex_config::TomlValue = serde_json::from_value(serde_json::json!({ + "hooks": { + "SessionStart": [{ + "hooks": [{ + "type": "command", + "command": "python3 /tmp/user.py", + }], + }], + "state": { + hook_list.hooks[0].key.clone(): { + "trusted_hash": hook_list.hooks[0].current_hash.clone(), + }, + }, + }, + }))?; + std::fs::write(&config_toml_path, toml::to_string(&trusted_user_config)?)?; + session.reload_user_config_layer().await; assert_eq!(session.hooks().preview_session_start(&request).len(), 1); diff --git a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs index 84e469e22d..8da6410a17 100644 --- a/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs +++ b/codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs @@ -371,6 +371,32 @@ async fn execve_permission_request_hook_short_circuits_prompt() -> anyhow::Resul .to_string(), ) .context("write hooks.json")?; + let config_toml_path = AbsolutePathBuf::try_from( + turn_context + .config + .codex_home + .join(codex_config::CONFIG_TOML_FILE), + ) + .context("build config.toml path")?; + let hook_list = codex_hooks::list_hooks(HooksConfig { + feature_enabled: true, + config_layer_stack: Some(turn_context.config.config_layer_stack.clone()), + ..HooksConfig::default() + }); + assert_eq!(hook_list.hooks.len(), 1); + let trusted_config_layer_stack = turn_context.config.config_layer_stack.with_user_config( + &config_toml_path, + serde_json::from_value(serde_json::json!({ + "hooks": { + "state": { + hook_list.hooks[0].key.clone(): { + "trusted_hash": hook_list.hooks[0].current_hash.clone(), + }, + }, + }, + })) + .context("build trusted hook state")?, + ); let mut hook_shell_argv = session .user_shell() @@ -382,7 +408,7 @@ async fn execve_permission_request_hook_short_circuits_prompt() -> anyhow::Resul .hooks .store(Arc::new(Hooks::new(HooksConfig { feature_enabled: true, - config_layer_stack: Some(turn_context.config.config_layer_stack.clone()), + config_layer_stack: Some(trusted_config_layer_stack), shell_program: Some(hook_shell_program), shell_args: hook_shell_argv, ..HooksConfig::default()