fix: handle deferred network proxy denials#19184
Conversation
Teach the model how to interpret managed network proxy allow/deny context and wire proxy denials into running shell and unified exec processes so blocked requests cancel promptly and surface as command failures. Co-authored-by: Codex noreply@openai.com
Keep the prompt-template updates out of the managed network proxy denial plumbing PR so they can land separately. Co-authored-by: Codex noreply@openai.com
Cover the network-denial cancellation plus timeout expiration variant in command/exec so app-server builds remain exhaustive. Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex noreply@openai.com
dylan-hurd-oai
left a comment
There was a problem hiding this comment.
generally looks good, but i'd like @jif-oai to look at unified exec. would be great to have slightly more detail in the denial messages
dylan-hurd-oai
left a comment
There was a problem hiding this comment.
I think we're okay to proceed for now, but would like the denial messages to be a bit clearer about where the network access denial is coming from. I think lack of specificity will lead to model confusion here
Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex noreply@openai.com
jif-oai
left a comment
There was a problem hiding this comment.
Unified exec still builds ExecOptions { expiration: ExecExpiration::DefaultTimeout, ... } without wiring attempt.network_denial_cancellation_token into the spawned request. The manager-side watcher covers the normal process after spawn, but anything inside the spawn/ preparation path, especially zsh-fork escalation setup, is not cancelled through the same expiration path as shell commands. That makes unified exec less robust than the shell path added in this PR.
Co-authored-by: Codex noreply@openai.com
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
codex/codex-rs/app-server/src/command_exec.rs
Lines 540 to 547 in 62cf07c
TimeoutOrCancellation now feeds this expiration arm, but the branch always sets timed_out = true; later exit handling maps any such termination to EXEC_TIMEOUT_EXIT_CODE. Cancellation-triggered stops (including network-denial cancellations) are therefore mislabeled as timeouts in responses.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Ensure deferred network denials emit failed unified-exec end events even when the process exits before it is stored, preserve short-lived denial output, and distinguish cancellation from timeouts across shell/app-server/Windows sandbox paths. Co-authored-by: Codex noreply@openai.com
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
| if active_calls.len() == 1 { | ||
| return active_calls.values().next().cloned(); | ||
| let calls = self.calls.lock().await; | ||
| if calls.active_calls.len() == 1 { |
There was a problem hiding this comment.
This makes denial cancellation work only when exactly one network-backed command is active. Can't we have to live execs? (or more ofc)
There was a problem hiding this comment.
Yes. Multiple live network-backed commands are possible. right now the proxy observer gives us an unattributed BlockedRequest, so this path only cancels when exactly one active call exists; with multiple active calls we cannot safely know which registration to fail, and intentionally avoid canceling the wrong one.
I've tried to fix this before but it ends up being a messy fix in the proxy code with registration/call ids in the headers and its brittle (an id via proxy credentials in the proxy URL).
I'll call this out explicitly in the code.
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Why
This bug is exposed by Guardian/auto-review approvals. With the managed network proxy enabled, a blocked network request can be reported back through the network approval service as an approval denial after the command has already started. Before this change, the shell and unified exec runtimes registered those network approval calls, but did not have a way to observe an async proxy denial as a cancellation/failure signal for the running process.
The result was confusing: Guardian/auto-review could correctly deny network access, but the command path could keep running or unregister the approval without surfacing the denial as the command failure.
What Changed
NetworkApprovalServicenow attaches a cancellation token to active and deferred network approvals.command/execnow handles the combined timeout-or-cancellation expiration variant used by the runtime.Verification
cargo test -p codex-core network_approval --libcargo clippy -p codex-app-server --all-targets -- -D warningscargo clippy -p codex-core --all-targets -- -D warnings