Commit Graph

6 Commits

  • [codex] Handle git pagination flags by position (#21381)
    ## Why
    
    This is a follow-up to the Windows Git safe-command bypass fix for
    BUGB-15601. Git's global `--paginate` / `-p` flags can route output
    through a configured pager, so they should not be auto-approved as safe
    before the subcommand. At the same time, `-p` after read-only
    subcommands like `log`, `diff`, and `show` is the common patch-output
    flag, so treating every `-p` as unsafe would make ordinary read-only
    inspection commands prompt unnecessarily.
    
    ## What Changed
    
    - Split Git option safety matching into explicit global-option and
    subcommand-option lists.
    - Treat global `git --paginate ...` and `git -p ...` as unsafe.
    - Keep post-subcommand patch usage such as `git log -p`, `git diff -p`,
    and `git show -p HEAD` safe.
    - Keep the pagination coverage with the shared Git safe-command
    implementation rather than the Windows wrapper tests.
    - Remove the stale `git_global_option_requires_prompt` helper now that
    safe-command Git option matching owns the prompt-required lists.
    
    ## Testing
    
    - `cargo test -p codex-shell-command`
  • Share Git safe-command logic on Windows (#21275)
    ## Why
    
    BUGB-15601 showed that the Windows safe-command path had drifted from
    the generic Git classifier. The Windows-specific Git parser could
    classify a PowerShell-wrapped `git` command as safe as soon as it found
    a safelisted subcommand, without applying the generic checks for unsafe
    subcommand options such as `--output`, `--ext-diff`, `--textconv`,
    `--paginate`, or `cat-file --filters`.
    
    The generic classifier already models the Git command boundary and the
    read-only argument checks more carefully, so Windows should reuse that
    logic instead of maintaining a smaller parallel parser.
    
    ## What Changed
    
    - Extracted the existing generic Git classification logic into
    `is_safe_git_command`.
    - Updated `windows_safe_commands.rs` to call that shared helper for
    parsed PowerShell `git` commands.
    - Removed the Windows-only Git subcommand safelist, including the
    `cat-file` allowance that was part of the reported bypass.
    - Added a Windows regression test that keeps PowerShell-wrapped Git
    commands with side-effecting options classified unsafe.
    - Made the full-path PowerShell test discover the installed PowerShell
    executable instead of depending on one hard-coded `pwsh.exe` path.
    
    ## Verification
    
    - `cargo test -p codex-shell-command
    rejects_git_subcommand_options_with_side_effects`
    - `cargo test -p codex-shell-command
    git_global_override_flags_are_not_safe`
    - `cargo test -p codex-shell-command
    windows_powershell_full_path_is_safe -- --nocapture`
    
    Co-authored-by: Codex <codex@openai.com>
  • execpolicy: unwrap PowerShell -Command wrappers on Windows (#20336)
    ## Why
    On Windows, Codex runs shell commands through a top-level
    `powershell.exe -NoProfile -Command ...` wrapper. `execpolicy` was
    matching that wrapper instead of the inner command, so prefix rules like
    `["git", "push"]` did not fire for PowerShell-wrapped commands even
    though the same normalization already happens for `bash -lc` on Unix.
    
    This change makes the Windows shell wrapper transparent to rule matching
    while preserving the existing Windows unmatched-command safelist and
    dangerous-command heuristics.
    
    ## What changed
    - add `parse_powershell_command_plain_commands()` in
    `shell-command/src/powershell.rs` to unwrap the top-level PowerShell
    `-Command` body with `extract_powershell_command()` and parse it with
    the existing PowerShell AST parser
    - update `core/src/exec_policy.rs` so `commands_for_exec_policy()`
    treats top-level PowerShell wrappers like `bash -lc` and evaluates rules
    against the parsed inner commands
    - carry a small `ExecPolicyCommandOrigin` through unmatched-command
    evaluation and expose `is_safe_powershell_words()` /
    `is_dangerous_powershell_words()` so Windows safelist and
    dangerous-command checks still work after unwrap
    - add Windows-focused tests for wrapped PowerShell prompt/allow matches,
    wrapper parsing, and unmatched safe/dangerous inner commands, and
    re-enable the end-to-end `execpolicy_blocks_shell_invocation` test on
    Windows
    
    ## Testing
    - `cargo test -p codex-shell-command`
  • shell-command: reuse a PowerShell parser process on Windows (#16057)
    ## Why
    
    `//codex-rs/shell-command:shell-command-unit-tests` became a real
    bottleneck in the Windows Bazel lane because repeated calls to
    `is_safe_command_windows()` were starting a fresh PowerShell parser
    process for every `powershell.exe -Command ...` assertion.
    
    PR #16056 was motivated by that same bottleneck, but its test-only
    shortcut was the wrong layer to optimize because it weakened the
    end-to-end guarantee that our runtime path really asks PowerShell to
    parse the command the way we expect.
    
    This PR attacks the actual cost center instead: it keeps the real
    PowerShell parser in the loop, but turns that parser into a long-lived
    helper process so both tests and the runtime safe-command path can reuse
    it across many requests.
    
    ## What Changed
    
    - add `shell-command/src/command_safety/powershell_parser.rs`, which
    keeps one mutex-protected parser process per PowerShell executable path
    and speaks a simple JSON-over-stdio request/response protocol
    - turn `shell-command/src/command_safety/powershell_parser.ps1` into a
    long-running parser server with comments explaining the protocol, the
    AST-shape restrictions, and why unsupported constructs are rejected
    conservatively
    - keep request ids and a one-time respawn path so a dead or
    desynchronized cached child fails closed instead of silently returning
    mixed parser output
    - preserve separate parser processes for `powershell.exe` and
    `pwsh.exe`, since they do not accept the same language surface
    - avoid a direct `PipelineChainAst` type reference in the PowerShell
    script so the parser service still runs under Windows PowerShell 5.1 as
    well as newer `pwsh`
    - make `shell-command/src/command_safety/windows_safe_commands.rs`
    delegate to the new parser utility instead of spawning a fresh
    PowerShell process for every parse
    - add a Windows-only unit test that exercises multiple sequential
    requests against the same parser process
    
    ## Testing
    
    - adds a Windows-only parser-reuse unit test in `powershell_parser.rs`
    - the main end-to-end verification for this change is the Windows CI
    lane, because the new service depends on real `powershell.exe` /
    `pwsh.exe` behavior
  • [codex] Block unsafe git global options from safe allowlist (#15796)
    ## Summary
    - block git global options that can redirect config, repository, or
    helper lookup from being auto-approved as safe
    - share the unsafe global-option predicate across the Unix and Windows
    git safety checks
    - add regression coverage for inline and split forms, including `bash
    -lc` and PowerShell wrappers
    
    ## Root cause
    The Unix safe-command gate only rejected `-c` and `--config-env`, even
    though the shared git parser already knew how to skip additional
    pre-subcommand globals such as `--git-dir`, `--work-tree`,
    `--exec-path`, `--namespace`, and `--super-prefix`. That let those
    arguments slip through safe-command classification on otherwise
    read-only git invocations and bypass approval. The Windows-specific
    safe-command path had the same trust-boundary gap for git global
    options.
  • chore: rename codex-command to codex-shell-command (#11378)
    This addresses some post-merge feedback on
    https://github.com/openai/codex/pull/11361:
    
    - crate rename
    - reuse `detect_shell_type()` utility