mirror of
https://github.com/openai/codex.git
synced 2026-11-04 00:24:43 +00:00
fix: prevent codex-backend from stealing originator (#22533)
## Why Remote control starts by letting `codex-backend` initialize against the app-server as an infrastructure health/proxy client before the real remote client connects. App-server initialization also sets the process-wide `originator` from `client_info.name`, so `codex-backend` could become the sticky originator for later model/API requests even after the real client initialized. ## What changed - Treat `codex-backend` as a non-originating initialize client, alongside the existing `codex_app_server_daemon` probe client. - Preserve normal per-connection initialize behavior, including session metadata and initialize analytics. - Add regression coverage that verifies `codex-backend` initialize does not replace the default originator. ## Testing - `cargo test -p codex-app-server --test all initialize_codex_backend_does_not_override_originator`
This commit is contained in:
1 parent
9c691b74d6
commit
fb7cfc813a
2 files changed
+29
-2
No files matched your search
@@ -13,7 +13,7 @@ use super::*;
|
|||||||
use crate::message_processor::ConnectionSessionState;
|
use crate::message_processor::ConnectionSessionState;
|
||||||
use crate::message_processor::InitializedConnectionSessionState;
|
use crate::message_processor::InitializedConnectionSessionState;
|
||||||
|
|
||||||
const DAEMON_PROBE_CLIENT_NAME: &str = "codex_app_server_daemon";
|
const NON_ORIGINATING_CLIENT_NAMES: &[&str] = &["codex_app_server_daemon", "codex-backend"];
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct InitializeRequestProcessor {
|
pub(crate) struct InitializeRequestProcessor {
|
||||||
@@ -92,7 +92,7 @@ impl InitializeRequestProcessor {
|
|||||||
}
|
}
|
||||||
let originator = name.clone();
|
let originator = name.clone();
|
||||||
let user_agent_suffix = format!("{name}; {version}");
|
let user_agent_suffix = format!("{name}; {version}");
|
||||||
let mutates_global_identity = name != DAEMON_PROBE_CLIENT_NAME;
|
let mutates_global_identity = !NON_ORIGINATING_CLIENT_NAMES.contains(&name.as_str());
|
||||||
let codex_home = self.config.codex_home.clone();
|
let codex_home = self.config.codex_home.clone();
|
||||||
if session
|
if session
|
||||||
.initialize(InitializedConnectionSessionState {
|
.initialize(InitializedConnectionSessionState {
|
||||||
|
|||||||
@@ -89,6 +89,33 @@ async fn initialize_probe_does_not_override_originator() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn initialize_codex_backend_does_not_override_originator() -> Result<()> {
|
||||||
|
let responses = Vec::new();
|
||||||
|
let server = create_mock_responses_server_sequence_unchecked(responses).await;
|
||||||
|
let codex_home = TempDir::new()?;
|
||||||
|
create_config_toml(codex_home.path(), &server.uri(), "never")?;
|
||||||
|
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||||
|
|
||||||
|
let message = timeout(
|
||||||
|
DEFAULT_READ_TIMEOUT,
|
||||||
|
mcp.initialize_with_client_info(ClientInfo {
|
||||||
|
name: "codex-backend".to_string(),
|
||||||
|
title: Some("Codex Backend".to_string()),
|
||||||
|
version: "0.1.0".to_string(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
let JSONRPCMessage::Response(response) = message else {
|
||||||
|
anyhow::bail!("expected initialize response, got {message:?}");
|
||||||
|
};
|
||||||
|
let InitializeResponse { user_agent, .. } = to_response::<InitializeResponse>(response)?;
|
||||||
|
|
||||||
|
assert!(user_agent.starts_with("codex_cli_rs/"));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn initialize_respects_originator_override_env_var() -> Result<()> {
|
async fn initialize_respects_originator_override_env_var() -> Result<()> {
|
||||||
let responses = Vec::new();
|
let responses = Vec::new();
|
||||||
|
|||||||
Reference in new issue
Block a user