Skip to content

Security parity: force shell:false for Git helpers on Windows #18

Description

@arcobaleno64

Context

Upstream openai/codex-plugin-cc v1.0.6 includes a security/robustness fix: Git commands are no longer routed through a shell.

References:

The upstream issue is that Git reference names can legally contain characters that Windows shells may interpret specially. Repository-derived Git arguments should therefore be passed as a literal argv array rather than re-parsed by a shell.

gemini-plugin-cc has the same relevant command path:

  • plugins/gemini/scripts/lib/git.mjs
    • git(cwd, args, options = {}) calls runCommand("git", args, { cwd, ...options })
    • gitChecked(cwd, args, options = {}) calls runCommandChecked("git", args, { cwd, ...options })
  • plugins/gemini/scripts/lib/process.mjs
    • runCommand() already supports options.shell
    • bare command names on Windows default to shell usage for .cmd/.ps1 wrapper compatibility

That Windows fallback is useful for npm/global CLI wrappers, but Git is directly executable on Windows and does not need shell expansion. Git arguments derived from repository state should be passed literally.

One important nuance in this fork: explicit --base refs are already validated by isSafeGitRef(), but auto-detected default branches come from repository state via refs/remotes/origin/HEAD and can still flow into branch diff collection.

Proposed change

Mirror the upstream hardening pattern in the Gemini helper layer:

  1. Update plugins/gemini/scripts/lib/git.mjs so all Git helper calls force shell: false, applied after caller-provided options:

    function git(cwd, args, options = {}) {
      return runCommand("git", args, { cwd, ...options, shell: false });
    }
    
    function gitChecked(cwd, args, options = {}) {
      return runCommandChecked("git", args, { cwd, ...options, shell: false });
    }
  2. Keep the existing Windows shell fallback for commands that actually need wrapper resolution, such as npm/global CLI binaries.

  3. Add regression coverage for an automatically detected default branch/ref name containing Windows shell-special characters.

  4. If the regression fixture needs direct Git invocation with shell: false, update tests/helpers.mjs to honor an explicit options.shell override, matching the upstream test-helper change.

Acceptance criteria

  • Git helper paths always invoke Git with shell: false.
  • Existing Gemini/AGY engine execution behavior remains unchanged.
  • Windows wrapper compatibility for non-Git commands is preserved.
  • A regression test covers an auto-detected default branch/ref name with shell-special characters.
  • The regression verifies that:
    • the branch name is passed to Git literally;
    • no adjacent shell command/helper is executed;
    • branch review target detection and diff collection still work.
  • Existing test suite passes.

Notes

This is not primarily a user-facing feature. It is a parity hardening change based on upstream openai/codex-plugin-cc v1.0.6 and should be prioritized ahead of a possible /gemini:transfer backlog item.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions