Skip to content

CLI sandbox: cannot commit because .git is read-only (“Unable to create .git/index.lock”) #7071

Open

Description

@lemmon

What version of Codex is running?

codex-cli 0.61.0

What subscription do you have?

Plus

Which model were you using?

gpt-5.1-codex-max (Medium)

What platform is your computer?

Darwin 24.6.0 arm64 arm

What issue are you seeing?

On the Codex CLI, git commit fails with fatal: Unable to create '/path/.git/index.lock': Operation not permitted. The .git directory appears read-only to the assistant process (even touch .git/test-permission fails). This blocks committing from the CLI.

Notes

  • Previously (older CLI version) commits worked; recent updates reintroduced the read-only .git behavior.
  • The underlying user shell (outside Codex) can commit fine; this is specific to the Codex sandbox permissionson .git.

What steps can reproduce the bug?

Uploaded thread: 019aa1d3-cb45-72b2-accf-b5b040ec1e9

What is the expected behavior?

No response

Additional information

No response

Activity

  1. added
    CLIIssues related to the Codex CLI
    sandboxIssues related to permissions or sandboxing
    on Nov 21, 2025
  2. github-actions commented on Nov 21, 2025

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  3. miraclebakelaser commented on Nov 21, 2025

    @miraclebakelaser
    Contributor

    This a model tuning issue that can be ameliorated with a prompt. Add this to your AGENTS.md:
    If a command fails due to insufficient permissions, you must elevate the command to the user for approval.

  4. ars-celare commented on Jan 8, 2026

    @ars-celare

    This is emphatically not fixed.

    Bro codex can’t even run bash commands 🤣 light years behind Claude.

    This is how people are commenting on Codex about this problem on Reddit. It's extremely damaging for the reputation of OpenAI!

    Personally, I've just installed Codex, I've no idea what the problem is with 'sandboxing', I do not want any git commands 'escalated' to me- in fact, I'd rather never touch a git commit again, all other LLMs are perfectly equipped to do this automatically, so why can't GPT? It's the kind of thing that will make me never use it again.

    This is an urgent and awful bug.

  5. jacobsapps commented on Jan 20, 2026

    @jacobsapps

    Yeah this is a huge pain, anyone got a workaround?

  6. lemieapp commented on Jan 21, 2026

    @lemieapp

    Same issue, codex suggested and applied a workaround to use a tmp folder outside the workspace to push

  7. Alan01252 commented on Jan 25, 2026

    @Alan01252

    I was able to workaround this by adding .git as an additional directory when spawning codex via the sdk/cli

  8. dmahurin commented on Jan 30, 2026

    @dmahurin

    @jacobsapps, @lemieapp,

    As mentioned in a older related issue, you could use a "git-shadow-dir". It is a writable, self referencing git worktree.

    #5034 (comment)

  9. gyf1214 commented on Feb 17, 2026

    @gyf1214

    Sadly this is intended:

    let mut subpaths: Vec<AbsolutePathBuf> = Vec::new();
    #[allow(clippy::expect_used)]
    let top_level_git = writable_root
    .join(".git")
    .expect(".git is a valid relative path");
    // This applies to typical repos (directory .git), worktrees/submodules
    // (file .git with gitdir pointer), and bare repos when the gitdir is the
    // writable root itself.
    let top_level_git_is_file = top_level_git.as_path().is_file();
    let top_level_git_is_dir = top_level_git.as_path().is_dir();
    if top_level_git_is_dir || top_level_git_is_file {
    if top_level_git_is_file
    && is_git_pointer_file(&top_level_git)
    && let Some(gitdir) = resolve_gitdir_from_file(&top_level_git)
    && !subpaths
    .iter()
    .any(|subpath| subpath.as_path() == gitdir.as_path())
    {
    subpaths.push(gitdir);
    }
    subpaths.push(top_level_git);
    }

    The subpaths are read-only sub-directory exceptions even when a directory is writable under workspace-write. Right now it includes .git (also gitdir when using worktree), .codex and .agents.

    The rationale does not make sense to me. When I use codex CLI/TUI, the git repo is mostly a local copy. I will use rules in remote repo to guard against dangerous operations (protected main, no force push, etc.).

    The "workaround" for me is simply comment out these lines and rebuild from source. But I would suggest to add a knob in workspace_write option to bypass this. Or, add a black list option explicitly with the current list as a default. A hidden hardcoded list is never a good practice in the long run.

    Adding a approval rule for git also works some time, but it works poorly under approval-policy = never in environments where interaction is not possible. I have to tell agent again and again to "run command with escalation, without shell wrapper or bash script", etc.

  10. K1-R1 commented on May 23, 2026

    @K1-R1

    I ran into the same safety/autonomy tradeoff: I wanted to keep Codex in a safer workspace-write posture, but normal local Git operations need writes under .git, so the options become either repeated approvals/manual Git or relaxing the sandbox much more than I wanted.

    I built a small local MCP server as a workaround: codex-safe-git.

    Repo: https://github.com/K1-R1/codex-safe-git

    It does not make .git broadly writable and it does not expose arbitrary shell/Git access. Instead it gives Codex a narrow, auditable Git tool surface for things like status, diff summaries, branch preparation, and exact-file commits. Remote operations are intentionally out of scope.

    Install:

    go install github.com/K1-R1/codex-safe-git/cmd/codex-safe-git-mcp@v0.4.3

    This is not a replacement for a proper upstream fix/config option, but it may be useful for people who want Codex to stay sandboxed while still letting it handle local Git workflows more autonomously.

  11. dlight commented on Jun 2, 2026

    @dlight

    It's kinda odd that there isn't a way to specify in the config file that agents should have permission to commit without prompting the human. Committing is such a cornerstone of coding tasks. Just let me manually specify that .git is writable, please.

    Also, allowing agents to run git outside the sandbox is such a bad idea. Actually running anything outside the sandbox is a bad idea. It gives much broader access than merely making .git writable.

  12. miraclebakelaser commented on Jun 2, 2026

    @miraclebakelaser
    Contributor

    @K1-R1 @dlight you can already do these things. See the rules docs.

  13. dlight commented on Jun 4, 2026

    @dlight

    @miraclebakelaser I want Codex to still run git sandboxed. I just don't want the sandbox to make .git read only. However this sandboxing rule appears to be hardcoded.

    The problem with allowing commands to run outside the sandbox is that there isn't a way to say "give this command write to .git, and nothing more". Instead, the command will bypass the sandbox entirely. So for example, if the sandbox doesn't allow network access, when you add an exception for a command, it will allow network access for that command too.

    Ideally I want zero exceptions on sandboxing, but instead tweak the sandbox to allow or disallow operations for all commands. Just like one can enable/disable networking for all commands inside the sandbox, marking .git writable should be possible, too.

  14. bbingz commented on Jul 24, 2026

    @bbingz

    Analysis (community)

    Thanks for tracking this — attempting a residual-focused analysis aligned with docs/contributing.md (invitation-only: analysis in-thread, no unsolicited PR).

    Observed (from issue + public residual signal)

    What version of Codex is running? codex-cli 0.61.0 ### What subscription do you have? Plus ### Which model were you using? gpt-5.1-codex-max (Medium) ### What platform is your computer? Darwin 24.6.0 arm64 arm ### What issue are you seeing? On the Codex CLI, git commit fails with fatal: Unable to create '/path/.git/index.lock': Operation not permitted. The .git directory appears read-only to the assistant process (even touch .git/test-permission fails). This blocks committing from the CLI. N

    Root-cause hypothesis (multi-surface)

    Reports mix at least three mechanisms that should be one analysis story:

    1. Intentional RO mount of .git under workspace-write / sandbox policy.
    2. Empty RO .git directory injection that poisons external tools.
    3. Windows Deny-ACL residue after unelevated/elevated sandbox transitions.

    High-level fix outline (not a PR)

    • Document intentional policy clearly if RO is required.
    • Never leave empty RO .git behind; prefer gitdir allowlist or redirect.
    • Windows: clear residual Deny ACEs after sandbox teardown.
    • Fail-first: commit/status under workspace-write with real repo fixture.

    Related open threads (cross-link, do not fork new)

    #7071, #15505, #14338, empty-.git cluster (#29492 family), Windows ACL #32880.

    Questions for maintainers

    1. Is the intended long-term policy documented for this area (especially sandbox gitdir / log TRACE defaults)?
    2. Preferred residual anchor issue if several open threads describe the same mechanism?
    3. If the high-level outline above is roughly aligned, would an invited PR with failing-first tests be welcome later — or is an internal fix preferred?

    Happy to refine with more measurements or code pointers. No unsolicited PR from me.

  15. bbingz commented on Jul 24, 2026

    @bbingz

    Analysis (community)

    Residual analysis for #7071 (cannot commit: .git read-only under sandbox) — invitation-only.

    Deterministic evidence (code on 5dd992acd3)

    • codex-rs/protocol/src/permissions.rs:
      • PROTECTED_METADATA_GIT_PATH_NAME = ".git"
      • FileSystemSandboxPolicy::workspace_write always calls
        append_default_read_only_project_root_subpath_if_no_explicit_rule(..., ".git") (≈L608)
      • forbidden_agent_metadata_write(...) blocks agent writes into protected metadata under restricted FS policy (≈L46–L80)
    • Seatbelt tests explicitly expect .git carveouts / blocked hooks: codex-rs/sandboxing/src/seatbelt_tests.rs (comments around pre-commit hook risk).

    This is policy-shaped, not a random mount glitch: workspace-write grants project write then re-asserts RO on .git.

    Root-cause hypothesis

    Three user-visible failure modes share this policy core:

    1. Intentional RO .git (security: hooks/config).
    2. Empty RO .git directory confusion for external tools.
    3. Windows Deny-ACL residue (separate but adjacent).

    High-level fix outline (not a PR)

    • Document “why .git is RO” in user-facing sandbox docs.
    • Prefer gitdir redirect / allowlisted git operations over silent RO failures.
    • Never leave empty RO .git that breaks git status outside the agent.
    • Fail-first: workspace-write fixture repo must git commit via approved path OR emit a clear policy error.

    Questions for maintainers

    1. Is RO .git still non-negotiable security policy?
    2. Preferred UX: explicit error vs allow worktree gitdir writes?
    3. Would an invited PR for clearer errors + tests be useful?

    No unsolicited PR from me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingsandboxIssues related to permissions or sandboxing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions