Compare commits

...

6 Commits

Author SHA1 Message Date
viyatb-oai
affe05fef2 chore: merge origin/main into codex/viyatb/permissions-network-constraints 2026-03-26 14:27:49 -07:00
viyatb-oai
0f407f3804 Merge remote-tracking branch 'origin/main' into codex/viyatb/permissions-network-constraints
# Conflicts:
#	codex-rs/core/src/config/network_proxy_spec.rs
2026-03-04 14:31:45 -08:00
viyatb-oai
f3d1633b62 fix(core): seed managed network defaults 2026-03-04 14:16:48 -08:00
viyatb-oai
fcad780b17 Merge branch 'main' into codex/viyatb/permissions-network-constraints 2026-02-19 19:20:21 -08:00
viyatb-oai
577d7a95fd chore(core): regenerate config schema 2026-02-19 15:50:53 -08:00
viyatb-oai
608635c4c4 fix(core): preserve managed network constraint semantics 2026-02-19 14:24:05 -08:00
8 changed files with 329 additions and 31 deletions

View File

@@ -927,6 +927,7 @@
"type": "boolean"
},
"allow_unix_sockets": {
"description": "When `requirements.toml` sets `experimental_network.allow_unix_sockets`, values here may further narrow access but must stay within the managed socket allowlist (subset semantics).",
"items": {
"type": "string"
},
@@ -936,6 +937,7 @@
"type": "boolean"
},
"allowed_domains": {
"description": "When `requirements.toml` sets `experimental_network.allowed_domains`, values here may further narrow access but must stay within the managed allowlist (subset semantics).",
"items": {
"type": "string"
},
@@ -948,6 +950,7 @@
"type": "boolean"
},
"denied_domains": {
"description": "When `requirements.toml` sets `experimental_network.denied_domains`, managed entries are always enforced. Values here can add more denied domains but cannot remove the managed ones (floor semantics).",
"items": {
"type": "string"
},

View File

@@ -448,6 +448,7 @@ async fn start_managed_network_proxy_applies_execpolicy_network_rules() -> anyho
let spec = crate::config::NetworkProxySpec::from_config_and_constraints(
NetworkProxyConfig::default(),
None,
None,
&SandboxPolicy::new_workspace_write_policy(),
)?;
let mut exec_policy = Policy::empty();
@@ -482,6 +483,7 @@ async fn start_managed_network_proxy_ignores_invalid_execpolicy_network_rules()
{
let spec = crate::config::NetworkProxySpec::from_config_and_constraints(
NetworkProxyConfig::default(),
None,
Some(NetworkConstraints {
allowed_domains: Some(vec!["managed.example.com".to_string()]),
managed_allowed_domains_only: Some(true),

View File

@@ -2176,6 +2176,7 @@ impl Config {
&& has_permission_profiles);
let (
configured_network_proxy_config,
configured_user_network,
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
@@ -2195,6 +2196,7 @@ impl Config {
let profile = resolve_permission_profile(permissions, default_permissions)?;
let configured_network_proxy_config =
network_proxy_config_from_profile_network(profile.network.as_ref());
let configured_user_network = profile.network.as_ref();
let (mut file_system_sandbox_policy, network_sandbox_policy) =
compile_permission_profile(
permissions,
@@ -2214,12 +2216,14 @@ impl Config {
}
(
configured_network_proxy_config,
configured_user_network,
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
)
} else {
let configured_network_proxy_config = NetworkProxyConfig::default();
let configured_user_network = None;
let mut sandbox_policy = cfg.derive_sandbox_policy(
sandbox_mode,
config_profile.sandbox_mode,
@@ -2241,6 +2245,7 @@ impl Config {
let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy);
(
configured_network_proxy_config,
configured_user_network,
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
@@ -2543,6 +2548,7 @@ impl Config {
let has_network_requirements = network_requirements.is_some();
let network = NetworkProxySpec::from_config_and_constraints(
configured_network_proxy_config,
configured_user_network,
network_requirements,
constrained_sandbox_policy.get(),
)

View File

@@ -86,6 +86,7 @@ impl NetworkProxySpec {
pub(crate) fn from_config_and_constraints(
config: NetworkProxyConfig,
user_network: Option<&crate::config::permissions::NetworkToml>,
requirements: Option<NetworkConstraints>,
sandbox_policy: &SandboxPolicy,
) -> std::io::Result<Self> {
@@ -95,6 +96,7 @@ impl NetworkProxySpec {
let (config, constraints) = if let Some(requirements) = requirements {
Self::apply_requirements(
config,
user_network,
&requirements,
sandbox_policy,
hard_deny_allowlist_misses,
@@ -187,6 +189,7 @@ impl NetworkProxySpec {
fn apply_requirements(
mut config: NetworkProxyConfig,
user_network: Option<&crate::config::permissions::NetworkToml>,
requirements: &NetworkConstraints,
sandbox_policy: &SandboxPolicy,
hard_deny_allowlist_misses: bool,
@@ -197,7 +200,13 @@ impl NetworkProxySpec {
let denylist_expansion_enabled = Self::denylist_expansion_enabled(sandbox_policy);
if let Some(enabled) = requirements.enabled {
config.network.enabled = enabled;
if enabled {
if user_network.and_then(|network| network.enabled).is_none() {
config.network.enabled = true;
}
} else {
config.network.enabled = false;
}
constraints.enabled = Some(enabled);
}
if let Some(http_port) = requirements.http_port {
@@ -207,14 +216,17 @@ impl NetworkProxySpec {
config.network.socks_url = format!("http://127.0.0.1:{socks_port}");
}
if let Some(allow_upstream_proxy) = requirements.allow_upstream_proxy {
config.network.allow_upstream_proxy = allow_upstream_proxy;
if !allow_upstream_proxy {
config.network.allow_upstream_proxy = false;
}
constraints.allow_upstream_proxy = Some(allow_upstream_proxy);
}
if let Some(dangerously_allow_non_loopback_proxy) =
requirements.dangerously_allow_non_loopback_proxy
{
config.network.dangerously_allow_non_loopback_proxy =
dangerously_allow_non_loopback_proxy;
if !dangerously_allow_non_loopback_proxy {
config.network.dangerously_allow_non_loopback_proxy = false;
}
constraints.dangerously_allow_non_loopback_proxy =
Some(dangerously_allow_non_loopback_proxy);
}
@@ -231,32 +243,53 @@ impl NetworkProxySpec {
requirements.allowed_domains.clone()
};
if let Some(allowed_domains) = managed_allowed_domains {
// Managed requirements seed the baseline allowlist. User additions
// can extend that baseline unless managed-only mode pins the
// effective allowlist to the managed set.
config.network.allowed_domains = if allowlist_expansion_enabled {
Self::merge_domain_lists(allowed_domains.clone(), &config.network.allowed_domains)
if allowlist_expansion_enabled {
// Seed the managed allowlist when the user left the field
// unspecified. If the user configured an allowlist, keep that
// narrower value and enforce the managed list as a subset
// constraint during validation.
if user_network
.and_then(|network| network.allowed_domains.as_ref())
.is_none()
{
config.network.allowed_domains = allowed_domains.clone();
}
} else {
allowed_domains.clone()
config.network.allowed_domains = allowed_domains.clone();
};
constraints.allowed_domains = Some(allowed_domains);
constraints.allowlist_expansion_enabled = Some(allowlist_expansion_enabled);
}
if let Some(denied_domains) = requirements.denied_domains.clone() {
config.network.denied_domains = if denylist_expansion_enabled {
Self::merge_domain_lists(denied_domains.clone(), &config.network.denied_domains)
if denylist_expansion_enabled {
// Managed denied domains are a floor. Preserve user-added entries,
// but ensure all managed entries are present.
for denied_domain in &denied_domains {
if !config
.network
.denied_domains
.iter()
.any(|existing| existing.eq_ignore_ascii_case(denied_domain))
{
config.network.denied_domains.push(denied_domain.clone());
}
}
} else {
denied_domains.clone()
};
config.network.denied_domains = denied_domains.clone();
}
constraints.denied_domains = Some(denied_domains);
constraints.denylist_expansion_enabled = Some(denylist_expansion_enabled);
}
if let Some(allow_unix_sockets) = requirements.allow_unix_sockets.clone() {
config.network.allow_unix_sockets = allow_unix_sockets.clone();
// Keep the user-configured socket allowlist if it is narrower.
// Managed requirements are enforced as a subset constraint during
// validation.
constraints.allow_unix_sockets = Some(allow_unix_sockets);
}
if let Some(allow_local_binding) = requirements.allow_local_binding {
config.network.allow_local_binding = allow_local_binding;
if !allow_local_binding {
config.network.allow_local_binding = false;
}
constraints.allow_local_binding = Some(allow_local_binding);
}
@@ -283,18 +316,6 @@ impl NetworkProxySpec {
SandboxPolicy::ReadOnly { .. } | SandboxPolicy::WorkspaceWrite { .. }
)
}
fn merge_domain_lists(mut managed: Vec<String>, user_entries: &[String]) -> Vec<String> {
for entry in user_entries {
if !managed
.iter()
.any(|managed_entry| managed_entry.eq_ignore_ascii_case(entry))
{
managed.push(entry.clone());
}
}
managed
}
}
fn apply_exec_policy_network_rules(config: &mut NetworkProxyConfig, exec_policy: &Policy) {

View File

@@ -1,4 +1,5 @@
use super::*;
use codex_network_proxy::NetworkMode;
use pretty_assertions::assert_eq;
#[test]
@@ -25,6 +26,10 @@ fn build_state_with_audit_metadata_threads_metadata_to_state() {
fn requirements_allowed_domains_are_a_baseline_for_user_allowlist() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["api.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
..Default::default()
@@ -32,6 +37,7 @@ fn requirements_allowed_domains_are_a_baseline_for_user_allowlist() {
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_read_only_policy(),
)
@@ -39,7 +45,7 @@ fn requirements_allowed_domains_are_a_baseline_for_user_allowlist() {
assert_eq!(
spec.config.network.allowed_domains,
vec!["*.example.com".to_string(), "api.example.com".to_string()]
vec!["api.example.com".to_string()]
);
assert_eq!(
spec.constraints.allowed_domains,
@@ -53,6 +59,11 @@ fn danger_full_access_keeps_managed_allowlist_and_denylist_fixed() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["evil.com".to_string()];
config.network.denied_domains = vec!["more-blocked.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["evil.com".to_string()]),
denied_domains: Some(vec!["more-blocked.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
denied_domains: Some(vec!["blocked.example.com".to_string()]),
@@ -61,6 +72,7 @@ fn danger_full_access_keeps_managed_allowlist_and_denylist_fixed() {
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::DangerFullAccess,
)
@@ -82,6 +94,10 @@ fn danger_full_access_keeps_managed_allowlist_and_denylist_fixed() {
fn managed_allowed_domains_only_disables_default_mode_allowlist_expansion() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["api.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
managed_allowed_domains_only: Some(true),
@@ -90,6 +106,7 @@ fn managed_allowed_domains_only_disables_default_mode_allowlist_expansion() {
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)
@@ -106,6 +123,10 @@ fn managed_allowed_domains_only_disables_default_mode_allowlist_expansion() {
fn managed_allowed_domains_only_ignores_user_allowlist_and_hard_denies_misses() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["api.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["managed.example.com".to_string()]),
managed_allowed_domains_only: Some(true),
@@ -114,6 +135,7 @@ fn managed_allowed_domains_only_ignores_user_allowlist_and_hard_denies_misses()
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)
@@ -135,6 +157,10 @@ fn managed_allowed_domains_only_ignores_user_allowlist_and_hard_denies_misses()
fn managed_allowed_domains_only_without_managed_allowlist_blocks_all_user_domains() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["api.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
managed_allowed_domains_only: Some(true),
..Default::default()
@@ -142,6 +168,7 @@ fn managed_allowed_domains_only_without_managed_allowlist_blocks_all_user_domain
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)
@@ -157,6 +184,10 @@ fn managed_allowed_domains_only_without_managed_allowlist_blocks_all_user_domain
fn managed_allowed_domains_only_blocks_all_user_domains_in_full_access_without_managed_list() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
allowed_domains: Some(vec!["api.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
managed_allowed_domains_only: Some(true),
..Default::default()
@@ -164,6 +195,7 @@ fn managed_allowed_domains_only_blocks_all_user_domains_in_full_access_without_m
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::DangerFullAccess,
)
@@ -179,6 +211,10 @@ fn managed_allowed_domains_only_blocks_all_user_domains_in_full_access_without_m
fn requirements_denied_domains_are_a_baseline_for_default_mode() {
let mut config = NetworkProxyConfig::default();
config.network.denied_domains = vec!["blocked.example.com".to_string()];
let user_network = crate::config::permissions::NetworkToml {
denied_domains: Some(vec!["blocked.example.com".to_string()]),
..Default::default()
};
let requirements = NetworkConstraints {
denied_domains: Some(vec!["managed-blocked.example.com".to_string()]),
..Default::default()
@@ -186,6 +222,7 @@ fn requirements_denied_domains_are_a_baseline_for_default_mode() {
let spec = NetworkProxySpec::from_config_and_constraints(
config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)
@@ -194,9 +231,225 @@ fn requirements_denied_domains_are_a_baseline_for_default_mode() {
assert_eq!(
spec.config.network.denied_domains,
vec![
"managed-blocked.example.com".to_string(),
"blocked.example.com".to_string()
"blocked.example.com".to_string(),
"managed-blocked.example.com".to_string()
]
);
assert_eq!(spec.constraints.denylist_expansion_enabled, Some(true));
}
#[test]
fn managed_requirements_preserve_more_restrictive_user_network_settings() -> std::io::Result<()> {
let mut user_config = NetworkProxyConfig::default();
user_config.network.enabled = false;
user_config.network.mode = NetworkMode::Limited;
user_config.network.allow_upstream_proxy = false;
user_config.network.dangerously_allow_non_loopback_proxy = false;
user_config.network.allowed_domains = vec!["api.openai.com".to_string()];
user_config.network.denied_domains = vec!["tracker.com".to_string(), "evil.com".to_string()];
user_config.network.allow_unix_sockets = vec!["/tmp/a.sock".to_string()];
user_config.network.allow_local_binding = false;
let requirements = NetworkConstraints {
enabled: Some(true),
http_port: Some(43128),
socks_port: Some(43129),
allow_upstream_proxy: Some(true),
dangerously_allow_non_loopback_proxy: Some(true),
dangerously_allow_all_unix_sockets: None,
allowed_domains: Some(vec!["*.openai.com".to_string()]),
managed_allowed_domains_only: None,
denied_domains: Some(vec!["evil.com".to_string()]),
allow_unix_sockets: Some(vec!["/tmp/a.sock".to_string(), "/tmp/b.sock".to_string()]),
allow_local_binding: Some(true),
};
let user_network = crate::config::permissions::NetworkToml {
enabled: Some(false),
allow_upstream_proxy: Some(false),
dangerously_allow_non_loopback_proxy: Some(false),
mode: Some(NetworkMode::Limited),
allowed_domains: Some(vec!["api.openai.com".to_string()]),
denied_domains: Some(vec!["tracker.com".to_string(), "evil.com".to_string()]),
allow_unix_sockets: Some(vec!["/tmp/a.sock".to_string()]),
allow_local_binding: Some(false),
..Default::default()
};
let spec = NetworkProxySpec::from_config_and_constraints(
user_config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)?;
let mut expected_config = NetworkProxyConfig::default();
expected_config.network.enabled = false;
expected_config.network.proxy_url = "http://127.0.0.1:43128".to_string();
expected_config.network.mode = NetworkMode::Limited;
expected_config.network.allow_upstream_proxy = false;
expected_config.network.dangerously_allow_non_loopback_proxy = false;
expected_config.network.enable_socks5 = true;
expected_config.network.socks_url = "http://127.0.0.1:43129".to_string();
expected_config.network.enable_socks5_udp = true;
expected_config.network.allowed_domains = vec!["api.openai.com".to_string()];
expected_config.network.denied_domains =
vec!["tracker.com".to_string(), "evil.com".to_string()];
expected_config.network.allow_unix_sockets = vec!["/tmp/a.sock".to_string()];
expected_config.network.allow_local_binding = false;
assert_eq!(spec.config, expected_config);
assert_eq!(
spec.constraints,
NetworkProxyConstraints {
enabled: Some(true),
mode: None,
allow_upstream_proxy: Some(true),
dangerously_allow_non_loopback_proxy: Some(true),
dangerously_allow_all_unix_sockets: None,
allowed_domains: Some(vec!["*.openai.com".to_string()]),
allowlist_expansion_enabled: Some(true),
denied_domains: Some(vec!["evil.com".to_string()]),
denylist_expansion_enabled: Some(true),
allow_unix_sockets: Some(vec!["/tmp/a.sock".to_string(), "/tmp/b.sock".to_string()]),
allow_local_binding: Some(true),
}
);
Ok(())
}
#[test]
fn managed_requirements_clamp_and_union_user_network_settings() -> std::io::Result<()> {
let mut user_config = NetworkProxyConfig::default();
user_config.network.enabled = true;
user_config.network.mode = NetworkMode::Full;
user_config.network.allow_upstream_proxy = true;
user_config.network.dangerously_allow_non_loopback_proxy = true;
user_config.network.denied_domains = vec!["tracker.com".to_string()];
user_config.network.allow_local_binding = true;
let requirements = NetworkConstraints {
enabled: Some(false),
http_port: None,
socks_port: None,
allow_upstream_proxy: Some(false),
dangerously_allow_non_loopback_proxy: Some(false),
dangerously_allow_all_unix_sockets: None,
allowed_domains: None,
managed_allowed_domains_only: None,
denied_domains: Some(vec!["evil.com".to_string()]),
allow_unix_sockets: None,
allow_local_binding: Some(false),
};
let user_network = crate::config::permissions::NetworkToml {
enabled: Some(true),
allow_upstream_proxy: Some(true),
dangerously_allow_non_loopback_proxy: Some(true),
mode: Some(NetworkMode::Full),
denied_domains: Some(vec!["tracker.com".to_string()]),
allow_local_binding: Some(true),
..Default::default()
};
let spec = NetworkProxySpec::from_config_and_constraints(
user_config,
Some(&user_network),
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)?;
let mut expected_config = NetworkProxyConfig::default();
expected_config.network.enabled = false;
expected_config.network.mode = NetworkMode::Full;
expected_config.network.allow_upstream_proxy = false;
expected_config.network.dangerously_allow_non_loopback_proxy = false;
expected_config.network.denied_domains =
vec!["tracker.com".to_string(), "evil.com".to_string()];
expected_config.network.allow_local_binding = false;
assert_eq!(spec.config, expected_config);
assert_eq!(
spec.constraints,
NetworkProxyConstraints {
enabled: Some(false),
mode: None,
allow_upstream_proxy: Some(false),
dangerously_allow_non_loopback_proxy: Some(false),
dangerously_allow_all_unix_sockets: None,
allowed_domains: None,
allowlist_expansion_enabled: None,
denied_domains: Some(vec!["evil.com".to_string()]),
denylist_expansion_enabled: Some(true),
allow_unix_sockets: None,
allow_local_binding: Some(false),
}
);
Ok(())
}
#[test]
fn managed_requirements_enable_proxy_when_user_omits_network_enabled() -> std::io::Result<()> {
let user_config = NetworkProxyConfig::default();
let requirements = NetworkConstraints {
enabled: Some(true),
..Default::default()
};
let spec = NetworkProxySpec::from_config_and_constraints(
user_config,
None,
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)?;
let mut expected_config = NetworkProxyConfig::default();
expected_config.network.enabled = true;
assert_eq!(spec.config, expected_config);
assert_eq!(
spec.constraints,
NetworkProxyConstraints {
enabled: Some(true),
..NetworkProxyConstraints::default()
}
);
Ok(())
}
#[test]
fn managed_requirements_seed_allowlist_when_user_omits_it() -> std::io::Result<()> {
let user_config = NetworkProxyConfig::default();
let requirements = NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["*.openai.com".to_string()]),
..Default::default()
};
let spec = NetworkProxySpec::from_config_and_constraints(
user_config,
None,
Some(requirements),
&SandboxPolicy::new_workspace_write_policy(),
)?;
let mut expected_config = NetworkProxyConfig::default();
expected_config.network.enabled = true;
expected_config.network.allowed_domains = vec!["*.openai.com".to_string()];
assert_eq!(spec.config, expected_config);
assert_eq!(
spec.constraints,
NetworkProxyConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["*.openai.com".to_string()]),
allowlist_expansion_enabled: Some(true),
..NetworkProxyConstraints::default()
}
);
Ok(())
}

View File

@@ -69,8 +69,17 @@ pub struct NetworkToml {
pub dangerously_allow_all_unix_sockets: Option<bool>,
#[schemars(with = "Option<NetworkModeSchema>")]
pub mode: Option<NetworkMode>,
/// When `requirements.toml` sets `experimental_network.allowed_domains`,
/// values here may further narrow access but must stay within the managed
/// allowlist (subset semantics).
pub allowed_domains: Option<Vec<String>>,
/// When `requirements.toml` sets `experimental_network.denied_domains`,
/// managed entries are always enforced. Values here can add more denied
/// domains but cannot remove the managed ones (floor semantics).
pub denied_domains: Option<Vec<String>>,
/// When `requirements.toml` sets `experimental_network.allow_unix_sockets`,
/// values here may further narrow access but must stay within the managed
/// socket allowlist (subset semantics).
pub allow_unix_sockets: Option<Vec<String>>,
pub allow_local_binding: Option<bool>,
}

View File

@@ -662,6 +662,7 @@ pub(crate) fn build_guardian_review_session_config(
.map(|network| network.value.clone());
guardian_config.permissions.network = Some(NetworkProxySpec::from_config_and_constraints(
live_network_config,
/*user_network*/ None,
network_constraints,
&SandboxPolicy::new_read_only_policy(),
)?);

View File

@@ -969,6 +969,7 @@ fn guardian_review_session_config_preserves_parent_network_proxy() {
let mut parent_config = test_config();
let network = NetworkProxySpec::from_config_and_constraints(
NetworkProxyConfig::default(),
None,
Some(NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["github.com".to_string()]),
@@ -1032,6 +1033,7 @@ fn guardian_review_session_config_uses_live_network_proxy_state() {
NetworkProxySpec::from_config_and_constraints(
parent_network,
None,
None,
parent_config.permissions.sandbox_policy.get(),
)
.expect("parent network proxy spec"),
@@ -1055,6 +1057,7 @@ fn guardian_review_session_config_uses_live_network_proxy_state() {
NetworkProxySpec::from_config_and_constraints(
live_network,
None,
None,
&SandboxPolicy::new_read_only_policy(),
)
.expect("live network proxy spec")