mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Preserve attachment Unix socket grants when controller policy is omitted (#46004)
## Why An omitted controller socket policy was treated as an explicit denial, preventing execution environments from supplying their own Unix socket grants. ## What changed - Preserve omission of `dangerously_allow_all_unix_sockets` separately from `false`, and retain explicitly empty `unix_sockets` maps. - Defer to attachment socket permissions when the controller supplies neither setting. Continue enforcing explicit restrictions, socket denials, and managed requirements. - Resolve omitted values to `false` for ordinary execution and remote configuration, preserving the default for commands without attachment grants. - Add debug logging for effective environment and remote execution network policies. ## Testing Add regression coverage for omitted, explicit, finite, empty, and managed socket policies through remote launch configuration, including live policy replacement and serialization round trips. Adjust remote environment tests to tolerate child-completion ordering and box large cold-resume test futures to reduce Windows stack usage. GitOrigin-RevId: 98a88d01cbb91aea1faaa03b3c414ef3be7af398
This commit is contained in:
@@ -493,7 +493,7 @@ impl NetworkToml {
|
||||
config.dangerously_allow_non_loopback_proxy = dangerously_allow_non_loopback_proxy;
|
||||
}
|
||||
if let Some(dangerously_allow_all_unix_sockets) = self.dangerously_allow_all_unix_sockets {
|
||||
config.dangerously_allow_all_unix_sockets = dangerously_allow_all_unix_sockets;
|
||||
config.dangerously_allow_all_unix_sockets = Some(dangerously_allow_all_unix_sockets);
|
||||
}
|
||||
if let Some(mode) = self.mode {
|
||||
config.mode = mode;
|
||||
@@ -512,8 +512,7 @@ impl NetworkToml {
|
||||
};
|
||||
proxy_unix_sockets.entries.insert(path.clone(), permission);
|
||||
}
|
||||
config.unix_sockets =
|
||||
(!proxy_unix_sockets.entries.is_empty()).then_some(proxy_unix_sockets);
|
||||
config.unix_sockets = Some(proxy_unix_sockets);
|
||||
}
|
||||
if let Some(allow_local_binding) = self.allow_local_binding {
|
||||
config.allow_local_binding = allow_local_binding;
|
||||
|
||||
@@ -266,7 +266,7 @@ impl NetworkProxySpec {
|
||||
NetworkProxyConfig {
|
||||
enabled: true,
|
||||
// Without a controller, the owner supplies the entire permission ceiling.
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
allow_local_binding: true,
|
||||
..NetworkProxyConfig::default()
|
||||
},
|
||||
@@ -308,6 +308,13 @@ impl NetworkProxySpec {
|
||||
format!("environment network policy violates managed requirements: {error}"),
|
||||
)
|
||||
})?;
|
||||
tracing::debug!(
|
||||
controller_policy = ?controller.map(Self::environment_policy),
|
||||
controller_allow_all_unix_sockets = ?controller.and_then(|spec| spec.config.dangerously_allow_all_unix_sockets),
|
||||
attachment_policy = ?policy,
|
||||
effective_policy = ?spec.environment_policy(),
|
||||
"resolved environment network policy"
|
||||
);
|
||||
Ok(spec)
|
||||
}
|
||||
|
||||
@@ -394,7 +401,7 @@ impl NetworkProxySpec {
|
||||
if let Some(dangerously_allow_all_unix_sockets) =
|
||||
requirements.dangerously_allow_all_unix_sockets
|
||||
{
|
||||
config.dangerously_allow_all_unix_sockets = dangerously_allow_all_unix_sockets;
|
||||
config.dangerously_allow_all_unix_sockets = Some(dangerously_allow_all_unix_sockets);
|
||||
constraints.dangerously_allow_all_unix_sockets =
|
||||
Some(dangerously_allow_all_unix_sockets);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,134 @@ fn domain_permissions(
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn attachment_socket_grants_respect_configured_restrictions_at_remote_launch()
|
||||
-> anyhow::Result<()> {
|
||||
let profile = PermissionProfile::workspace_write();
|
||||
let owner = EnvironmentNetworkPolicy::from_config(
|
||||
&NetworkProxyConfig {
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
/*managed_allowed_domains_only*/ false,
|
||||
);
|
||||
for (name, toml, required, expected) in [
|
||||
("omitted", "", None, true),
|
||||
(
|
||||
"explicit_deny",
|
||||
"dangerously_allow_all_unix_sockets = false",
|
||||
None,
|
||||
false,
|
||||
),
|
||||
(
|
||||
"explicit_allow",
|
||||
"dangerously_allow_all_unix_sockets = true",
|
||||
None,
|
||||
true,
|
||||
),
|
||||
(
|
||||
"finite",
|
||||
"unix_sockets = { '/tmp/allowed.sock' = 'allow', '/tmp/denied.sock' = 'deny' }",
|
||||
None,
|
||||
false,
|
||||
),
|
||||
("empty", "unix_sockets = {}", None, false),
|
||||
(
|
||||
"managed_deny",
|
||||
"dangerously_allow_all_unix_sockets = true",
|
||||
Some(false),
|
||||
false,
|
||||
),
|
||||
] {
|
||||
let configured: codex_config::permissions_toml::NetworkToml = toml::from_str(toml)?;
|
||||
let controller = NetworkProxySpec::from_config_and_constraints(
|
||||
configured.to_network_proxy_config(),
|
||||
Some(NetworkConstraints {
|
||||
enabled: Some(true),
|
||||
dangerously_allow_all_unix_sockets: required,
|
||||
..Default::default()
|
||||
}),
|
||||
&profile,
|
||||
)?;
|
||||
let composed = NetworkProxySpec::for_environment(
|
||||
Some(&controller),
|
||||
&owner,
|
||||
&profile,
|
||||
&Policy::empty(),
|
||||
)?;
|
||||
assert_eq!(
|
||||
composed.config.dangerously_allow_all_unix_sockets,
|
||||
Some(expected),
|
||||
"{name}"
|
||||
);
|
||||
let state = Arc::new(controller.build_state_with_audit_metadata(Default::default())?);
|
||||
let proxy = NetworkProxy::builder()
|
||||
.state(Arc::clone(&state))
|
||||
.managed_by_codex(false)
|
||||
.build()
|
||||
.await?;
|
||||
let scoped = proxy.for_execution(
|
||||
"socket-test",
|
||||
name,
|
||||
format!("socket-{name}"),
|
||||
Some(composed.environment_policy()),
|
||||
/*fallback_policy_decider*/ None,
|
||||
)?;
|
||||
let launch = scoped.remote_launch_config().await?;
|
||||
assert_eq!(
|
||||
launch.proxy.dangerously_allow_all_unix_sockets, expected,
|
||||
"{name}"
|
||||
);
|
||||
assert_eq!(
|
||||
launch.proxy.unix_sockets, composed.config.unix_sockets,
|
||||
"{name}"
|
||||
);
|
||||
if name == "finite" {
|
||||
assert_eq!(launch.proxy.unix_sockets, controller.config.unix_sockets);
|
||||
}
|
||||
if name == "omitted" {
|
||||
// Inheritance must not grant sockets to ordinary controller-only commands.
|
||||
assert!(
|
||||
!proxy
|
||||
.remote_launch_config()
|
||||
.await?
|
||||
.proxy
|
||||
.dangerously_allow_all_unix_sockets
|
||||
);
|
||||
state.add_allowed_domain("granted.example").await?;
|
||||
assert!(
|
||||
scoped
|
||||
.remote_launch_config()
|
||||
.await?
|
||||
.proxy
|
||||
.dangerously_allow_all_unix_sockets
|
||||
);
|
||||
|
||||
// A live handle must also honor a subsequently installed explicit restriction.
|
||||
let restricted = NetworkProxySpec::from_config_and_constraints(
|
||||
NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: Some(false),
|
||||
..Default::default()
|
||||
},
|
||||
/*requirements*/ None,
|
||||
&profile,
|
||||
)?;
|
||||
proxy
|
||||
.replace_config_state(restricted.build_config_state_for_spec()?)
|
||||
.await?;
|
||||
assert!(
|
||||
!scoped
|
||||
.remote_launch_config()
|
||||
.await?
|
||||
.proxy
|
||||
.dangerously_allow_all_unix_sockets
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_state_with_audit_metadata_threads_metadata_to_state() {
|
||||
let spec = NetworkProxySpec {
|
||||
@@ -119,7 +247,7 @@ fn environment_policy_replaces_soft_controller_allowlist_and_preserves_denials()
|
||||
"/private/tmp/controller.sock".to_string(),
|
||||
"/tmp/allowed.sock".to_string(),
|
||||
]);
|
||||
owner.dangerously_allow_all_unix_sockets = true;
|
||||
owner.dangerously_allow_all_unix_sockets = Some(true);
|
||||
owner.allow_local_binding = true;
|
||||
let owner_policy =
|
||||
EnvironmentNetworkPolicy::from_config(&owner, /*managed_allowed_domains_only*/ false);
|
||||
@@ -162,7 +290,7 @@ fn environment_policy_replaces_soft_controller_allowlist_and_preserves_denials()
|
||||
);
|
||||
owner.unix_sockets.clone_from(&spec.config.unix_sockets);
|
||||
owner.allow_upstream_proxy = false;
|
||||
owner.dangerously_allow_all_unix_sockets = false;
|
||||
owner.dangerously_allow_all_unix_sockets = Some(false);
|
||||
owner.allow_local_binding = false;
|
||||
assert_eq!(
|
||||
restricted.environment_policy(),
|
||||
|
||||
@@ -2383,6 +2383,17 @@ async fn deferred_executor_spawn_agent_inherits_ready_step_environments(
|
||||
],
|
||||
)
|
||||
.await;
|
||||
// If the child finishes after the parent's last request, its completion
|
||||
// notification triggers one more parent request. Allow either ordering.
|
||||
mount_sse_once(
|
||||
&server,
|
||||
sse(vec![
|
||||
ev_response_created("resp-child-completion"),
|
||||
ev_assistant_message("msg-child-completion", "done"),
|
||||
ev_completed("resp-child-completion"),
|
||||
]),
|
||||
)
|
||||
.await;
|
||||
let mut builder = test_codex()
|
||||
.with_exec_server_url(format!("ws://{}", listener.local_addr()?))
|
||||
.with_config(move |config| {
|
||||
|
||||
@@ -134,7 +134,7 @@ for family in (socket.AF_NETLINK, getattr(socket, 'AF_VSOCK', 40)):
|
||||
let mut config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
proxy_url: "http://127.0.0.1:9".to_string(),
|
||||
dangerously_allow_all_unix_sockets,
|
||||
dangerously_allow_all_unix_sockets: Some(dangerously_allow_all_unix_sockets),
|
||||
..Default::default()
|
||||
};
|
||||
if allow_path {
|
||||
|
||||
@@ -126,8 +126,9 @@ pub struct NetworkProxyConfig {
|
||||
pub allow_upstream_proxy: bool,
|
||||
#[serde(default)]
|
||||
pub dangerously_allow_non_loopback_proxy: bool,
|
||||
#[serde(default)]
|
||||
pub dangerously_allow_all_unix_sockets: bool,
|
||||
/// When no socket map is set, omission defers to attachment policy; execution defaults to false.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub dangerously_allow_all_unix_sockets: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub mode: NetworkMode,
|
||||
#[serde(default)]
|
||||
@@ -166,7 +167,7 @@ impl Default for NetworkProxyConfig {
|
||||
enable_socks5_udp: true,
|
||||
allow_upstream_proxy: true,
|
||||
dangerously_allow_non_loopback_proxy: false,
|
||||
dangerously_allow_all_unix_sockets: false,
|
||||
dangerously_allow_all_unix_sockets: None,
|
||||
mode: NetworkMode::default(),
|
||||
domains: None,
|
||||
unix_sockets: None,
|
||||
@@ -345,7 +346,7 @@ impl NetworkProxyConfig {
|
||||
for entry in entries {
|
||||
unix_sockets.entries.insert(entry, permission);
|
||||
}
|
||||
self.unix_sockets = (!unix_sockets.entries.is_empty()).then_some(unix_sockets);
|
||||
self.unix_sockets = Some(unix_sockets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +429,9 @@ pub(crate) fn clamp_bind_addrs(
|
||||
"SOCKS5 proxy",
|
||||
"dangerously_allow_non_loopback_proxy",
|
||||
);
|
||||
if cfg.allow_unix_sockets().is_empty() && !cfg.dangerously_allow_all_unix_sockets {
|
||||
if cfg.allow_unix_sockets().is_empty()
|
||||
&& !cfg.dangerously_allow_all_unix_sockets.unwrap_or(false)
|
||||
{
|
||||
return (http_addr, socks_addr);
|
||||
}
|
||||
|
||||
@@ -694,7 +697,7 @@ mod tests {
|
||||
enable_socks5_udp: true,
|
||||
allow_upstream_proxy: true,
|
||||
dangerously_allow_non_loopback_proxy: false,
|
||||
dangerously_allow_all_unix_sockets: false,
|
||||
dangerously_allow_all_unix_sockets: None,
|
||||
mode: NetworkMode::Full,
|
||||
domains: None,
|
||||
unix_sockets: None,
|
||||
@@ -888,7 +891,6 @@ mod tests {
|
||||
"enable_socks5_udp": true,
|
||||
"allow_upstream_proxy": true,
|
||||
"dangerously_allow_non_loopback_proxy": false,
|
||||
"dangerously_allow_all_unix_sockets": false,
|
||||
"mode": "full",
|
||||
"domains": {
|
||||
"example.com": "deny",
|
||||
@@ -1070,7 +1072,7 @@ mod tests {
|
||||
fn clamp_bind_addrs_forces_loopback_when_all_unix_sockets_enabled() {
|
||||
let cfg = NetworkProxyConfig {
|
||||
dangerously_allow_non_loopback_proxy: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let http_addr = "0.0.0.0:3128".parse::<SocketAddr>().unwrap();
|
||||
|
||||
@@ -27,7 +27,9 @@ impl EnvironmentNetworkPolicy {
|
||||
domains: config.domains.clone(),
|
||||
unix_sockets: config.unix_sockets.clone(),
|
||||
allow_upstream_proxy: config.allow_upstream_proxy,
|
||||
dangerously_allow_all_unix_sockets: config.dangerously_allow_all_unix_sockets,
|
||||
dangerously_allow_all_unix_sockets: config
|
||||
.dangerously_allow_all_unix_sockets
|
||||
.unwrap_or(false),
|
||||
allow_local_binding: config.allow_local_binding,
|
||||
managed_allowed_domains_only,
|
||||
}
|
||||
@@ -45,11 +47,16 @@ impl EnvironmentNetworkPolicy {
|
||||
crate::normalize_host,
|
||||
);
|
||||
}
|
||||
// An omitted controller policy leaves socket permissions to the attachment;
|
||||
// an explicitly empty socket map still supplies a restrictive ceiling.
|
||||
let inherited_allow_all = config
|
||||
.dangerously_allow_all_unix_sockets
|
||||
.unwrap_or(config.unix_sockets.is_none());
|
||||
let inherited_sockets = config.unix_sockets.take().unwrap_or_default();
|
||||
let mut effective_sockets = self.unix_sockets.clone().unwrap_or_default();
|
||||
|
||||
// "Allow all" cannot override a socket denied by either policy.
|
||||
let inherited_permits_all = config.dangerously_allow_all_unix_sockets
|
||||
let inherited_permits_all = inherited_allow_all
|
||||
&& !inherited_sockets
|
||||
.entries
|
||||
.values()
|
||||
@@ -77,7 +84,8 @@ impl EnvironmentNetworkPolicy {
|
||||
|
||||
// Enable permissions only when both controller and owner allow them.
|
||||
config.unix_sockets = (!effective_sockets.entries.is_empty()).then_some(effective_sockets);
|
||||
config.dangerously_allow_all_unix_sockets = inherited_permits_all && owner_permits_all;
|
||||
config.dangerously_allow_all_unix_sockets =
|
||||
Some(inherited_permits_all && owner_permits_all);
|
||||
config.allow_upstream_proxy &= self.allow_upstream_proxy;
|
||||
config.allow_local_binding &= self.allow_local_binding;
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ impl NetworkProxyBuilder {
|
||||
#[cfg(target_os = "windows")]
|
||||
let (current_cfg, runtime_settings, mut windows_ingress) = {
|
||||
let current_cfg = config::NetworkProxyConfig {
|
||||
dangerously_allow_all_unix_sockets: false,
|
||||
dangerously_allow_all_unix_sockets: Some(false),
|
||||
unix_sockets: None,
|
||||
..current_cfg
|
||||
};
|
||||
@@ -461,7 +461,7 @@ impl NetworkProxyRuntimeSettings {
|
||||
config.allow_unix_sockets().into()
|
||||
},
|
||||
dangerously_allow_all_unix_sockets: !cfg!(target_os = "windows")
|
||||
&& config.dangerously_allow_all_unix_sockets,
|
||||
&& config.dangerously_allow_all_unix_sockets.unwrap_or(false),
|
||||
mitm_ca_trust_bundle,
|
||||
})
|
||||
}
|
||||
@@ -940,6 +940,20 @@ impl NetworkProxy {
|
||||
};
|
||||
broker_only_config.set_credential_broker_enabled(/*enabled*/ true);
|
||||
broker_only_config.set_allowed_domains(vec!["*".to_string()]);
|
||||
// Omission and explicit false have the same effective broker-only permissions.
|
||||
if !config.dangerously_allow_all_unix_sockets.unwrap_or(false) {
|
||||
broker_only_config.dangerously_allow_all_unix_sockets =
|
||||
config.dangerously_allow_all_unix_sockets;
|
||||
}
|
||||
if config
|
||||
.unix_sockets
|
||||
.as_ref()
|
||||
.is_some_and(|sockets| sockets.entries.is_empty())
|
||||
{
|
||||
broker_only_config
|
||||
.unix_sockets
|
||||
.clone_from(&config.unix_sockets);
|
||||
}
|
||||
let broker_only = brokerage_created_default_allowlist && config == broker_only_config;
|
||||
|
||||
let environment_policy = self
|
||||
@@ -962,6 +976,7 @@ impl NetworkProxy {
|
||||
"environment network policy requires an enabled executor proxy"
|
||||
);
|
||||
let proxy = crate::RemoteNetworkProxyConfig::from_effective_config(&config)?;
|
||||
tracing::debug!(network_config = ?proxy, "resolved remote execution network configuration");
|
||||
let (environment_id, execution_id) = self
|
||||
.execution_scope
|
||||
.as_ref()
|
||||
@@ -1774,7 +1789,7 @@ mod tests {
|
||||
proxy_url: "http://0.0.0.0:3128".to_string(),
|
||||
socks_url: "http://0.0.0.0:8081".to_string(),
|
||||
dangerously_allow_non_loopback_proxy: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
unix_sockets: Some(unix_sockets.clone()),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
@@ -2153,7 +2168,7 @@ mod tests {
|
||||
.await?;
|
||||
|
||||
for allow_all in [false, true] {
|
||||
config.dangerously_allow_all_unix_sockets = allow_all;
|
||||
config.dangerously_allow_all_unix_sockets = Some(allow_all);
|
||||
let replacement = crate::state::build_config_state(config.clone(), Default::default())?;
|
||||
proxy.replace_config_state(replacement).await?;
|
||||
let prepared = proxy
|
||||
@@ -2310,8 +2325,10 @@ mod tests {
|
||||
let _permit = WINDOWS_INGRESS_TEST_LOCK.acquire().await.unwrap();
|
||||
let mut config = NetworkProxyConfig {
|
||||
dangerously_allow_plaintext_credential_injection: true,
|
||||
dangerously_allow_all_unix_sockets: Some(false),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
config.set_allow_unix_sockets(Vec::new());
|
||||
config.set_credential_broker_enabled(/*enabled*/ true);
|
||||
config.configure_credential_broker_environment(&HashMap::from([(
|
||||
"GH_HOST".to_string(),
|
||||
|
||||
@@ -87,7 +87,9 @@ impl RemoteNetworkProxyConfig {
|
||||
enable_socks5: config.enable_socks5,
|
||||
enable_socks5_udp: config.enable_socks5_udp,
|
||||
allow_upstream_proxy: config.allow_upstream_proxy,
|
||||
dangerously_allow_all_unix_sockets: config.dangerously_allow_all_unix_sockets,
|
||||
dangerously_allow_all_unix_sockets: config
|
||||
.dangerously_allow_all_unix_sockets
|
||||
.unwrap_or(false),
|
||||
mode: config.mode,
|
||||
domains: config.domains.clone(),
|
||||
unix_sockets: config.unix_sockets.clone(),
|
||||
@@ -101,7 +103,7 @@ impl RemoteNetworkProxyConfig {
|
||||
enable_socks5: self.enable_socks5,
|
||||
enable_socks5_udp: self.enable_socks5_udp,
|
||||
allow_upstream_proxy: self.allow_upstream_proxy,
|
||||
dangerously_allow_all_unix_sockets: self.dangerously_allow_all_unix_sockets,
|
||||
dangerously_allow_all_unix_sockets: Some(self.dangerously_allow_all_unix_sockets),
|
||||
mode: self.mode,
|
||||
domains: self.domains,
|
||||
unix_sockets: self.unix_sockets,
|
||||
|
||||
@@ -8,6 +8,36 @@ use crate::NetworkProxyAuditMetadata;
|
||||
use crate::NetworkProxyConfig;
|
||||
use crate::NetworkProxyState;
|
||||
|
||||
#[test]
|
||||
fn optional_socket_policy_preserves_input_and_resolves_at_remote_boundary() {
|
||||
for allow_all in [None, Some(false), Some(true)] {
|
||||
let mut config = NetworkProxyConfig {
|
||||
dangerously_allow_all_unix_sockets: allow_all,
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
config.set_allow_unix_sockets(Vec::new());
|
||||
let serialized = serde_json::to_value(&config).expect("serialize config");
|
||||
assert_eq!(
|
||||
serialized.get("dangerously_allow_all_unix_sockets"),
|
||||
allow_all.map(serde_json::Value::Bool).as_ref()
|
||||
);
|
||||
assert_eq!(serialized["unix_sockets"], serde_json::json!({}));
|
||||
assert_eq!(
|
||||
serde_json::from_value::<NetworkProxyConfig>(serialized).expect("deserialize config"),
|
||||
config
|
||||
);
|
||||
|
||||
let remote = RemoteNetworkProxyConfig::from_effective_config(&config)
|
||||
.expect("supported remote config");
|
||||
assert_eq!(
|
||||
remote.dangerously_allow_all_unix_sockets,
|
||||
allow_all.unwrap_or(false)
|
||||
);
|
||||
config.dangerously_allow_all_unix_sockets = Some(allow_all.unwrap_or(false));
|
||||
assert_eq!(remote.into_network_proxy_config(), config);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip_preserves_supported_effective_settings() {
|
||||
let mut config = NetworkProxyConfig {
|
||||
@@ -15,7 +45,7 @@ fn round_trip_preserves_supported_effective_settings() {
|
||||
enable_socks5: false,
|
||||
enable_socks5_udp: false,
|
||||
allow_upstream_proxy: false,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
mode: NetworkMode::Limited,
|
||||
allow_local_binding: true,
|
||||
..NetworkProxyConfig::default()
|
||||
|
||||
@@ -786,7 +786,11 @@ impl NetworkProxyState {
|
||||
}
|
||||
|
||||
let guard = self.state.read().await;
|
||||
if guard.config.dangerously_allow_all_unix_sockets {
|
||||
if guard
|
||||
.config
|
||||
.dangerously_allow_all_unix_sockets
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -2038,7 +2042,7 @@ mod tests {
|
||||
|
||||
let config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
|
||||
@@ -2055,7 +2059,7 @@ mod tests {
|
||||
|
||||
let config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
|
||||
@@ -2071,7 +2075,7 @@ mod tests {
|
||||
|
||||
let config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
|
||||
@@ -2084,7 +2088,7 @@ mod tests {
|
||||
|
||||
let config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..NetworkProxyConfig::default()
|
||||
};
|
||||
|
||||
@@ -2244,7 +2248,7 @@ mod tests {
|
||||
async fn unix_socket_allow_all_flag_bypasses_allowlist() {
|
||||
let state = network_proxy_state_for_policy({
|
||||
let mut network = network_settings(&["example.com"], &[]);
|
||||
network.dangerously_allow_all_unix_sockets = true;
|
||||
network.dangerously_allow_all_unix_sockets = Some(true);
|
||||
network
|
||||
});
|
||||
|
||||
@@ -2262,7 +2266,7 @@ mod tests {
|
||||
&[],
|
||||
std::slice::from_ref(&socket_path),
|
||||
);
|
||||
network.dangerously_allow_all_unix_sockets = true;
|
||||
network.dangerously_allow_all_unix_sockets = Some(true);
|
||||
network
|
||||
});
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ pub fn validate_policy_against_constraints(
|
||||
.dangerously_allow_all_unix_sockets
|
||||
.unwrap_or(constraints.allow_unix_sockets.is_none());
|
||||
validate(
|
||||
config.dangerously_allow_all_unix_sockets,
|
||||
config.dangerously_allow_all_unix_sockets.unwrap_or(false),
|
||||
move |candidate| {
|
||||
if *candidate && !allow_all_unix_sockets {
|
||||
Err(invalid_value(
|
||||
|
||||
@@ -520,7 +520,7 @@ async fn linux_unix_socket_grant_uses_effective_managed_policy() -> anyhow::Resu
|
||||
let state = build_config_state(
|
||||
NetworkProxyConfig {
|
||||
enabled: true,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
NetworkProxyConstraints::default(),
|
||||
|
||||
@@ -813,7 +813,7 @@ async fn prepared_managed_network_context_takes_precedence_over_live_proxy_socke
|
||||
let network_config = NetworkProxyConfig {
|
||||
enabled: true,
|
||||
mode: NetworkMode::Full,
|
||||
dangerously_allow_all_unix_sockets: true,
|
||||
dangerously_allow_all_unix_sockets: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let state = build_config_state(network_config, NetworkProxyConstraints::default())?;
|
||||
|
||||
@@ -1787,7 +1787,8 @@ async fn overview_cold_resume_honors_working_directory_selection() -> Result<()>
|
||||
("session", true, true),
|
||||
("session", false, false),
|
||||
] {
|
||||
let mut app = make_test_app().await;
|
||||
// Keep the large setup and cold-resume futures off the Windows test stack.
|
||||
let mut app = Box::pin(make_test_app()).await;
|
||||
trust_fixture_folders(&mut app);
|
||||
let chosen = app.config.codex_home.join("chosen");
|
||||
let overridden = app.config.codex_home.join("overridden");
|
||||
@@ -1814,7 +1815,8 @@ async fn overview_cold_resume_honors_working_directory_selection() -> Result<()>
|
||||
)
|
||||
.expect("create historical session"),
|
||||
)?;
|
||||
let mut app_server = crate::start_embedded_app_server_for_picker(&app.config).await?;
|
||||
let mut app_server =
|
||||
Box::pin(crate::start_embedded_app_server_for_picker(&app.config)).await?;
|
||||
app.launch_cwd = chosen.to_path_buf();
|
||||
app.harness_overrides.cwd = cli_cwd.then(|| {
|
||||
if runtime_cwd {
|
||||
@@ -1838,8 +1840,7 @@ async fn overview_cold_resume_honors_working_directory_selection() -> Result<()>
|
||||
drop(selection);
|
||||
let pending_loading =
|
||||
crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal).clone();
|
||||
app.select_agents_overview_thread(&mut tui, &mut app_server, thread_id)
|
||||
.await?;
|
||||
Box::pin(app.select_agents_overview_thread(&mut tui, &mut app_server, thread_id)).await?;
|
||||
// The widget replacement clears the terminal; feedback must remain until the next draw.
|
||||
let loading =
|
||||
crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal).clone();
|
||||
@@ -1858,21 +1859,19 @@ async fn overview_cold_resume_honors_working_directory_selection() -> Result<()>
|
||||
insta::allow_duplicates! {
|
||||
insta::assert_snapshot!(loading_text.trim_end(), @"Loading task…");
|
||||
}
|
||||
app.handle_tui_event(&mut tui, &mut app_server, TuiEvent::Draw)
|
||||
.await?;
|
||||
Box::pin(app.handle_tui_event(&mut tui, &mut app_server, TuiEvent::Draw)).await?;
|
||||
assert_ne!(
|
||||
crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal),
|
||||
&loading,
|
||||
);
|
||||
let observed = app_server
|
||||
.resume_thread(
|
||||
&app.local_settings,
|
||||
app.config.clone(),
|
||||
thread_id,
|
||||
crate::app_server_session::ResumeModelSettings::PreserveExistingThread,
|
||||
)
|
||||
.await?
|
||||
.session;
|
||||
let observed = Box::pin(app_server.resume_thread(
|
||||
&app.local_settings,
|
||||
app.config.clone(),
|
||||
thread_id,
|
||||
crate::app_server_session::ResumeModelSettings::PreserveExistingThread,
|
||||
))
|
||||
.await?
|
||||
.session;
|
||||
assert_eq!(
|
||||
(app.config.cwd.clone(), observed.cwd),
|
||||
(expected_cwd.clone(), expected_cwd),
|
||||
|
||||
Reference in New Issue
Block a user