mirror of
https://github.com/openai/codex.git
synced 2026-04-30 19:32:04 +03:00
[codex] Add danger-full-access denylist-only network mode (#16946)
## Summary This adds `experimental_network.danger_full_access_denylist_only` for orgs that want yolo / danger-full-access sessions to keep full network access while still enforcing centrally managed deny rules. When the flag is true and the session sandbox is `danger-full-access`, the network proxy starts with: - domain allowlist set to `*` - managed domain `deny` entries enforced - upstream proxy use allowed - all Unix sockets allowed - local/private binding allowed Caveat: the denylist is best effort only. In yolo / danger-full-access mode, Codex or the model can use an allowed socket or other local/private network path to bypass the proxy denylist, so this should not be treated as a hard security boundary. The flag is intentionally scoped to `SandboxPolicy::DangerFullAccess`. Read-only and workspace-write modes keep the existing managed/user allowlist, denylist, Unix socket, and local-binding behavior. This does not enable the non-loopback proxy listener setting; that still requires its own explicit config. This also threads the new field through config requirements parsing, app-server protocol/schema output, config API mapping, and the TUI debug config output. ## How to use Add the flag under `[experimental_network]` in the network policy config that is delivered to Codex. The setting is not under `[permissions]`. ```toml [experimental_network] enabled = true danger_full_access_denylist_only = true [experimental_network.domains] "blocked.example.com" = "deny" "*.blocked.example.com" = "deny" ``` With that configuration, yolo / danger-full-access sessions get broad network access except for the managed denied domains above. The denylist remains a best-effort proxy policy because the session may still use allowed sockets to bypass it. Other sandbox modes do not get the wildcard domain allowlist or the socket/local-binding relaxations from this flag. ## Verification - `cargo test -p codex-config network_requirements` - `cargo test -p codex-core network_proxy_spec` - `cargo test -p codex-app-server map_requirements_toml_to_api` - `cargo test -p codex-tui debug_config_output` - `cargo test -p codex-app-server-protocol` - `just write-app-server-schema` - `just fmt` - `just fix -p codex-config -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-tui` - `just fix -p codex-core -p codex-config` - `git diff --check` - `cargo clean`
This commit is contained in:
@@ -237,6 +237,8 @@ pub struct NetworkRequirementsToml {
|
||||
/// When true, only managed `allowed_domains` are respected while managed
|
||||
/// network enforcement is active. User allowlist entries are ignored.
|
||||
pub managed_allowed_domains_only: Option<bool>,
|
||||
/// In danger-full-access mode, allow all network access and enforce managed deny entries.
|
||||
pub danger_full_access_denylist_only: Option<bool>,
|
||||
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
|
||||
pub allow_local_binding: Option<bool>,
|
||||
}
|
||||
@@ -255,6 +257,8 @@ struct RawNetworkRequirementsToml {
|
||||
/// When true, only managed `allowed_domains` are respected while managed
|
||||
/// network enforcement is active. User allowlist entries are ignored.
|
||||
managed_allowed_domains_only: Option<bool>,
|
||||
/// In danger-full-access mode, allow all network access and enforce managed deny entries.
|
||||
danger_full_access_denylist_only: Option<bool>,
|
||||
#[serde(default)]
|
||||
denied_domains: Option<Vec<String>>,
|
||||
unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
|
||||
@@ -279,6 +283,7 @@ impl<'de> Deserialize<'de> for NetworkRequirementsToml {
|
||||
domains,
|
||||
allowed_domains,
|
||||
managed_allowed_domains_only,
|
||||
danger_full_access_denylist_only,
|
||||
denied_domains,
|
||||
unix_sockets,
|
||||
allow_unix_sockets,
|
||||
@@ -307,6 +312,7 @@ impl<'de> Deserialize<'de> for NetworkRequirementsToml {
|
||||
domains: domains
|
||||
.or_else(|| legacy_domain_permissions_from_lists(allowed_domains, denied_domains)),
|
||||
managed_allowed_domains_only,
|
||||
danger_full_access_denylist_only,
|
||||
unix_sockets: unix_sockets
|
||||
.or_else(|| legacy_unix_socket_permissions_from_list(allow_unix_sockets)),
|
||||
allow_local_binding,
|
||||
@@ -359,6 +365,8 @@ pub struct NetworkConstraints {
|
||||
/// When true, only managed `allowed_domains` are respected while managed
|
||||
/// network enforcement is active. User allowlist entries are ignored.
|
||||
pub managed_allowed_domains_only: Option<bool>,
|
||||
/// In danger-full-access mode, allow all network access and enforce managed deny entries.
|
||||
pub danger_full_access_denylist_only: Option<bool>,
|
||||
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
|
||||
pub allow_local_binding: Option<bool>,
|
||||
}
|
||||
@@ -384,6 +392,7 @@ impl From<NetworkRequirementsToml> for NetworkConstraints {
|
||||
dangerously_allow_all_unix_sockets,
|
||||
domains,
|
||||
managed_allowed_domains_only,
|
||||
danger_full_access_denylist_only,
|
||||
unix_sockets,
|
||||
allow_local_binding,
|
||||
} = value;
|
||||
@@ -396,6 +405,7 @@ impl From<NetworkRequirementsToml> for NetworkConstraints {
|
||||
dangerously_allow_all_unix_sockets,
|
||||
domains,
|
||||
managed_allowed_domains_only,
|
||||
danger_full_access_denylist_only,
|
||||
unix_sockets,
|
||||
allow_local_binding,
|
||||
}
|
||||
@@ -1808,6 +1818,7 @@ allowed_approvals_reviewers = ["user"]
|
||||
allow_upstream_proxy = false
|
||||
dangerously_allow_all_unix_sockets = true
|
||||
managed_allowed_domains_only = true
|
||||
danger_full_access_denylist_only = true
|
||||
allow_local_binding = false
|
||||
|
||||
[experimental_network.domains]
|
||||
@@ -1858,6 +1869,10 @@ allowed_approvals_reviewers = ["user"]
|
||||
sourced_network.value.managed_allowed_domains_only,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
sourced_network.value.danger_full_access_denylist_only,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
sourced_network.value.unix_sockets.as_ref(),
|
||||
Some(&NetworkUnixSocketPermissionsToml {
|
||||
@@ -1881,6 +1896,7 @@ allowed_approvals_reviewers = ["user"]
|
||||
dangerously_allow_all_unix_sockets = true
|
||||
allowed_domains = ["api.example.com", "*.openai.com"]
|
||||
managed_allowed_domains_only = true
|
||||
danger_full_access_denylist_only = true
|
||||
denied_domains = ["blocked.example.com"]
|
||||
allow_unix_sockets = ["/tmp/example.sock"]
|
||||
allow_local_binding = false
|
||||
@@ -1925,6 +1941,10 @@ allowed_approvals_reviewers = ["user"]
|
||||
sourced_network.value.managed_allowed_domains_only,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
sourced_network.value.danger_full_access_denylist_only,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
sourced_network.value.unix_sockets.as_ref(),
|
||||
Some(&NetworkUnixSocketPermissionsToml {
|
||||
|
||||
Reference in New Issue
Block a user