Skip to content

G6|Network Proxy:先有权联网,再有托管出站 ​

先别把 network.enabled 当成代理开关 ​

读完 B3,下一件错事是在 permission profile 里打开网络,以为托管代理已经在拦流量。或者反过来:打开 Feature::NetworkProxy,以为 Seatbelt 可以继续禁网,代理会「代替」操作系统。

判断先说清楚:代理是沙箱已经获得网络能力之后的托管 HTTP/SOCKS 策略层。 双门闩:Feature::NetworkProxy 且 permission_profile.network_sandbox_policy().is_enabled()(core/src/config/mod.rs:3620-3629)。少一扇门,enabled 仍是 false。profile 里的 network.enabled 管的是 沙箱能不能出网,注释写明它 不单独启动 managed proxy(permissions.rs:130-133)。

B3 的三套旋钮管「这条命令物理上能不能跑、问不问、前缀禁令」。G6 管「已经能跑的进程,出站请求走哪、问不问、密钥怎么换」。


1. 先有权联网,再有代理 ​

network-proxy crate 在本机拉 HTTP(默认 127.0.0.1:3128)和 SOCKS5(默认 8081)监听(network-proxy/README.md:1-12)。Windows 会在一段端口里轮询,占满再退回 ephemeral loopback。

策略正文写在 permission profile 的 [permissions.<profile>.network](README :20-65),不是只写在 [features]。flag 打开的是「要不要启用这套托管代理」;域名表、mode、MITM hooks、unix socket 白名单跟 profile 走。扁平 network_proxy = true 只开门闩。

名单默认是拒绝:没有任何 allow 条目时,代理挡住请求直到你配 allowlist。全局 * 被拒;只认精确 host 或 *.openai.com / **.openai.com。allow_local_binding 默认 false:本机/私网要显式放行,而且 解析到私网 IP 的 hostname 即使在名单里也拦。

沙箱怎么「指过去」:Seatbelt 只放行 localhost:代理端口(sandboxing/src/seatbelt_tests.rs:444);Linux helper 在 managed 开启时要 proxy-only 网络(landlock.rs:8-12)。exec 还会带上 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY。模型不用自己 export。

flag 默认关:Feature::NetworkProxy 是 Experimental,default_enabled: false(G4)。嵌套 [features.network_proxy] 可以再叠 mode、credential_broker。

没有双门闩会怎样?要么 profile 一开网就透明代理,用户没同意 Experimental;要么只开了 flag、沙箱仍禁网,代理空转、模型用 curl 直接打外网失败却以为「策略生效了」。能力在 B3,策略执行在 G6。


2. allow / deny / ask 与 ExecPolicy 汇合 ​

代理侧决策是 NetworkPolicyDecision::{Deny, Ask}(network-proxy/src/network_policy.rs:66-68)。allow 走 allowlist;未命中则 deny 或升级成问人。Session 启动会把 ExecPolicy 里的网络规则合并进来(session/mod.rs 一侧)——前缀禁令和域名表不是两套互相看不见的名单。

问人只在 Managed profile 且审批不是 Never 时发生(tools/network_approval.rs:190-196)。DangerFullAccess 或 --yolo 不会再弹「这个域名行不行」:你已经拆掉同意旋钮。core 把 proxy payload 翻成审批文案(network_policy_decision.rs),前端只投影,不自己解析 SOCKS。

没有「三分决策」会怎样?要么所有出站静默放行,flag 变成装饰;要么所有未名单域名直接杀进程,CI 里的合法依赖下载变成沙箱 violation。问人是同意链的延伸,不是第四套 OS 沙箱。


3. credential broker:环境里假凭证,代理内侧换真密钥 ​

CredentialBroker(credential_broker.rs:43-65)把真密钥留在代理进程里。spawn 给沙箱的环境变量是标记或假值(CODEX_NETWORK_PROXY_CREDENTIAL_BROKER_ACTIVE、@alias:)。子进程就算 env 泄露,也拿不到 raw token。出站经过代理时,broker 按 host / 别名换成真凭证。

这不是「再发明一套 keyring」。登录态仍在 B5 的 AuthManager。broker 只解决:已经获准出网的命令,不要把密钥铺进沙箱环境。

没有 broker 会怎样?要么禁止一切带 token 的 curl,模型办不成事;要么把 OPENAI_API_KEY 写进 exec env,一次 env 或 crash dump 就漏。假凭证是出站层的职责,不是 ExecPolicy 能用前缀禁令模拟的。


4. limited / full、MITM、升级出沙箱 ​

limited 不是「差不多只读」的形容词。README 钉死:只许 GET / HEAD / OPTIONS;HTTPS CONNECT 和 :443 的 SOCKS 必须走 MITM 才能执行 method 政策,否则直接拦;SOCKS UDP、非 HTTPS 的 SOCKS TCP 在 limited 里也拦(README :116-118)。full 才按名单走任意方法。limited 或配了 MITM hooks 时自动开 MITM:CA 私钥留在代理内存,spawn 出去的进程只拿到 $CODEX_HOME/proxy/ 下不可变的公钥包。

拦下来的响应是 403,带 x-proxy-error:blocked-by-allowlist / blocked-by-denylist / blocked-by-method-policy / blocked-by-policy。这是给 Orchestrator 和人看的策略结果,不是 Seatbelt 的 deny 日志。

B3 的 escalation 会 bypass managed network:命令一旦被批准升出沙箱,OS 不再把流量指到 3128。代理拦不住一条已经 Danger 的 shell。Seatbelt / Landlock / bwrap 管的是进程还能不能直接 Dial;代理管的是被指到 loopback 之后的请求。

dangerously_allow_non_loopback_proxy 默认关:监听夹在 loopback。打开等于把策略口暴露到局域网,那是运维事故,不是产品默认。

三角不要焊成一句「网络安全」:

层问的问题不回答
ExecPolicy这条命令前缀许不许 spawn域名级 HTTP
沙箱 NetworkAccess进程能不能出网出网之后去哪
Network Proxy出站请求 allow / deny / ask,密钥怎么换命令该不该启动

没有这层切割会怎样?升出沙箱的命令仍以为自己被代理罩着;或把 Seatbelt 禁网当成「已经有了 allowlist」。抄的时候先抄 B3 的能力门,再抄 G6 的出站门。


5. 结语:带走一句话 ​

出站策略是第三套旋钮——先有权联网,再有托管代理的 allow/deny/ask 和假凭证——不要把 profile 的 network.enabled 或 Seatbelt 禁网当成代理本身。