mirror of
https://github.com/openai/codex.git
synced 2026-11-07 08:34:29 +00:00
Reject sessions with unloadable required managed hooks (#38394)
## Why Hooks supplied as managed requirements must not be silently skipped when their handlers cannot be loaded. ## What changed - Fail session and app-server thread startup when an enabled managed requirement contains an invalid matcher, an empty command, or an unsupported handler type. - Keep load failures for ordinary managed configuration hooks as warnings, and do not enforce managed hook requirements while the hooks feature is disabled. ## Testing Added hook-engine, core session, and app-server coverage for valid and invalid managed hook requirements. GitOrigin-RevId: 91a23b0c1d85e143aba6aabe874c5274e52fc6b2
This commit is contained in:
1 parent
683716cee9
commit
ef596c68ca
9 files changed
+440
-40
No files matched your search
@@ -1083,6 +1083,87 @@ async fn thread_start_fails_when_required_mcp_server_fails_to_initialize() -> Re
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_start_fails_when_managed_hook_matcher_is_invalid() -> Result<()> {
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
std::fs::write(
|
||||
codex_home.path().join("requirements.toml"),
|
||||
r#"[hooks]
|
||||
|
||||
[[hooks.PreToolUse]]
|
||||
matcher = "["
|
||||
|
||||
[[hooks.PreToolUse.hooks]]
|
||||
type = "command"
|
||||
command = "echo managed"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized()
|
||||
.await?;
|
||||
let request_id = app_server
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let error: JSONRPCError = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
app_server.read_stream_until_error_message(RequestId::Integer(request_id)),
|
||||
)
|
||||
.await??;
|
||||
|
||||
assert!(
|
||||
error.error.message.contains("managed") && error.error.message.contains("invalid matcher"),
|
||||
"unexpected error message: {}",
|
||||
error.error.message
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_start_fails_when_managed_hook_handler_is_unsupported() -> Result<()> {
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;
|
||||
std::fs::write(
|
||||
codex_home.path().join("requirements.toml"),
|
||||
r#"[hooks]
|
||||
|
||||
[[hooks.PreToolUse]]
|
||||
matcher = "^Bash$"
|
||||
|
||||
[[hooks.PreToolUse.hooks]]
|
||||
type = "mcp_tool"
|
||||
server = "security"
|
||||
tool = "scan"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.build_initialized()
|
||||
.await?;
|
||||
let request_id = app_server
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let error: JSONRPCError = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
app_server.read_stream_until_error_message(RequestId::Integer(request_id)),
|
||||
)
|
||||
.await??;
|
||||
|
||||
assert!(
|
||||
error.error.message.contains("MCP tool hook"),
|
||||
"unexpected error message: {}",
|
||||
error.error.message
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_start_emits_mcp_server_status_updated_notifications() -> Result<()> {
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
|
||||
Reference in new issue
Block a user