mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:12:04 +00:00
## Why Private IP destinations always bypassed inherited upstream proxies, preventing their use for private networks reachable through an upstream VPN proxy. ## What changed - Add `codex exec-server --proxy-private-ips-via-upstream`, also configurable with `CODEX_EXEC_SERVER_PROXY_PRIVATE_IPS_VIA_UPSTREAM=true`. The setting defaults to disabled. - Allow permitted RFC 1918, carrier-grade NAT, and IPv6 unique-local destinations to use an applicable upstream proxy. Loopback and link-local destinations retain direct routing, and destination access policy still applies. - Keep connections direct when no valid upstream proxy applies or `allow_upstream_proxy=false`. Errors after selecting an upstream proxy do not trigger a direct retry. - Rename `ExecServerRuntimePaths` to `ExecServerRuntimeOptions` and carry the routing setting from executor startup into the managed network proxy. ## Testing Add routing coverage for private address ranges, special-use addresses, and public targets with the option enabled and disabled. Verify that HTTP and CONNECT requests still enforce destination allowlists and denylists, and update the CLI help snapshot. GitOrigin-RevId: b7c9cc7da0e0f545694a6521b74c9b36b7b92769
89 lines
3.2 KiB
Rust
89 lines
3.2 KiB
Rust
//! Resolves managed fork sources through the existing name/ID lookup before final configuration.
|
|
//! The temporary app-server never starts a thread or executes a turn.
|
|
|
|
use super::*;
|
|
|
|
pub(super) struct ForkNetwork {
|
|
pub cloud_config_bundle: CloudConfigBundleLoader,
|
|
pub policy: codex_app_server_client::EmbeddedNetworkPolicy,
|
|
}
|
|
|
|
pub(super) async fn fork_source(
|
|
args: &mut crate::cli::ForkArgs,
|
|
config: &Config,
|
|
arg0_paths: &Arg0DispatchPaths,
|
|
cli_overrides: &[(String, codex_config::TomlValue)],
|
|
loader_overrides: &LoaderOverrides,
|
|
network: ForkNetwork,
|
|
strict_config: bool,
|
|
) -> anyhow::Result<std::path::PathBuf> {
|
|
let state_db = codex_core::init_state_db(config).await;
|
|
let environment_manager = EnvironmentManager::from_codex_home(
|
|
config.codex_home.clone(),
|
|
Some(ExecServerRuntimeOptions::from_optional_paths(
|
|
arg0_paths.codex_self_exe.clone(),
|
|
arg0_paths.codex_linux_sandbox_exe.clone(),
|
|
)?),
|
|
network.policy.bind(config.http_client_factory()),
|
|
)
|
|
.await?;
|
|
let client = InProcessAppServerClient::start(InProcessClientStartArgs {
|
|
arg0_paths: arg0_paths.clone(),
|
|
config: std::sync::Arc::new(config.clone()),
|
|
cli_overrides: cli_overrides.to_vec(),
|
|
loader_overrides: LoaderOverrides {
|
|
ignore_project_config: true,
|
|
..loader_overrides.clone()
|
|
},
|
|
strict_config,
|
|
cloud_config_bundle: network.cloud_config_bundle,
|
|
embedded_network_policy: network.policy,
|
|
feedback: CodexFeedback::new(),
|
|
log_db: None,
|
|
state_db: state_db.clone(),
|
|
environment_manager: std::sync::Arc::new(environment_manager),
|
|
config_warnings: Vec::new(),
|
|
session_source: SessionSource::Exec,
|
|
enable_codex_api_key_env: true,
|
|
client_name: "codex_exec".to_string(),
|
|
client_version: env!("CARGO_PKG_VERSION").to_string(),
|
|
experimental_api: true,
|
|
mcp_server_openai_form_elicitation: false,
|
|
opt_out_notification_methods: Vec::new(),
|
|
channel_capacity: DEFAULT_IN_PROCESS_CHANNEL_CAPACITY,
|
|
})
|
|
.await?;
|
|
let result = async {
|
|
let lookup = crate::cli::ResumeArgs {
|
|
session_id: Some(args.session_id.clone()),
|
|
last: false,
|
|
all: true,
|
|
images: Vec::new(),
|
|
prompt: None,
|
|
};
|
|
let thread_id = resolve_resume_thread_id(&client, config, state_db.as_ref(), &lookup)
|
|
.await?
|
|
.ok_or_else(|| anyhow::anyhow!("Session not found: {}", args.session_id))?;
|
|
let source: ThreadReadResponse = send_request_with_response(
|
|
&client,
|
|
ClientRequest::ThreadRead {
|
|
request_id: RequestId::Integer(1),
|
|
params: ThreadReadParams {
|
|
thread_id: thread_id.clone(),
|
|
include_turns: false,
|
|
},
|
|
},
|
|
"thread/read",
|
|
)
|
|
.await
|
|
.map_err(anyhow::Error::msg)?;
|
|
args.session_id = thread_id;
|
|
Ok::<_, anyhow::Error>(latest_thread_cwd(&source.thread).await)
|
|
}
|
|
.await;
|
|
let shutdown = client.shutdown().await;
|
|
let source_cwd = result?;
|
|
shutdown?;
|
|
Ok(source_cwd)
|
|
}
|