Skip to content

[Bug] Cursor adapter: false "Shell/Read blocked" reports caused by shell-tool name mismatch + native-exec rejections #399

Description

@Wibias

Summary

On Cursor-backed models, agents repeatedly tell the user that shell/read access is blocked even when Codex is already running with full sandbox access and the Codex shell bridge tool still works.

This is not a missing-permissions bug. It is a Cursor adapter / tool-catalog / messaging bug:

  1. Cursor-native Shell / Read / Grep / LS are rejected by policy (default nativeLocalExec off).
  2. OpenCodex guidance and rejection text push exec_command.
  3. The actually working Codex shell bridge is often advertised / callable as shell_command and/or the long MCP display name (mcp_opencodex-responses_shell_command / mcp_opencodex-responses_exec_command).
  4. Tool-catalog truncation changes which exact name is visible turn-to-turn.
  5. Models treat the resulting "tool not found" / native-exec rejection as a hard sandbox block and emit user-facing lines like:
    • Shell access is blocked here
    • Shell and Read are blocked in this environment

Observed across multiple Codex Desktop chats on Cursor models (including while diagnosing this issue).

Expected

With Codex full-access sandbox already enabled:

  • Calling the Codex shell bridge succeeds.
  • If Cursor-native Shell/Read are unavailable, rejection text should clearly say "use Codex bridge tool X (aliases: ...)", not sound like a sandbox denial.
  • Agents should not tell the user that shell/read are blocked unless the Codex bridge shell tool itself fails.
  • The shell bridge tool should remain available even when the Cursor client-tool catalog is truncated.

Actual

  • Cursor-native Shell/Read get rejected with copy that points at exec_command.
  • The live callable shell tool name flips between turns among:
    • shell_command
    • exec_command
    • long mcp_opencodex-responses_* display names
    • occasionally Cursor-native Shell appearing in guidance/catalog text
  • Models then emit false "blocked" commentary even though a later shell_command / bridge call works in the same chat.
  • Catalog truncation notes (Cursor's transport limit allows N of M client tools this turn) amplify the confusion.

Evidence / code pointers

Relevant OpenCodex paths:

  • src/adapters/cursor/tool-definitions.ts
    • hardcodes shell guidance around exec_command
    • warns against neighboring-agent tools Read / Grep / Glob / Bash / LS
    • mentions long display alias mcp_opencodex-responses_exec_command
  • src/adapters/cursor/request-builder.ts
    • applyCursorToolBudget / toolPriority / catalogLimitNote
    • truncation can omit many tools; shell bridge is not specially pinned beyond generic bare-tool priority
  • src/adapters/cursor/native-exec-shell.ts
    • rejection: Cursor native shell unavailable; use exec_command
  • src/adapters/cursor/native-exec-fs.ts
    • rejection: Cursor native filesystem read/ls/grep unavailable; use exec_command / apply_patch
  • src/adapters/cursor/exec-policy.ts
    • default native local exec is off unless explicitly opted in
  • docs: docs-site/src/content/docs/reference/configuration.md
    • documents unsafeAllowNativeLocalExec as an intentional opt-in, not the default path

Live reproduction pattern (redacted):

  1. Use a cursor/* model through OpenCodex.
  2. Ensure Codex sandbox is full-access / approval never.
  3. Ask the agent to inspect local files/run shell.
  4. Observe either:
    • wrong tool name (Shell / missing short name) fails, or
    • Cursor-native Shell/Read rejected with "use exec_command"
  5. Agent announces shell/read are blocked.
  6. Same chat can then succeed with shell_command / long MCP shell alias.

Why this is harmful

  • Users waste time chasing phantom permission problems.
  • Agents abandon working shell paths and invent alternate broken tool names.
  • Multi-turn work becomes flaky because catalog truncation + naming drift changes the callable shell identifier every turn.

Proposed fix

Minimum durable fix set:

  1. Unify the shell tool name across catalog shell_type, Cursor guidance, rejection messages, and docs.
    • Today shell_command and exec_command conflict.
  2. Pin the shell bridge tool through catalog truncation in applyCursorToolBudget / toolPriority so truncation can drop niche MCP tools but never the shell bridge (and ideally also keep apply_patch).
  3. Rewrite rejection/guidance copy:
    • say Cursor-native Shell/Read are disabled by policy
    • point to the exact Codex bridge tool + aliases
    • explicitly state this is not a sandbox denial when Codex full-access is already active
  4. Add anti-false-block guidance:
    • never tell the user shell/read are blocked unless the Codex bridge shell tool also fails
    • if a shell alias is missing, retry listed aliases instead of escalating to "blocked" language
  5. Make alias resolution boring and bidirectional so all of these resolve to one backend tool:
    • shell_command
    • exec_command
    • mcp_opencodex-responses_shell_command
    • mcp_opencodex-responses_exec_command
  6. Regression tests covering:
    • full-access sandbox
    • native Cursor Shell/Read rejected
    • bridge shell still works
    • truncated catalogs still retain bridge shell
    • guidance/rejection text does not claim "Shell access is blocked"

Non-goals / not the fix

  • Do not treat this as a Codex sandbox_mode / approval_policy problem.
  • Do not require enabling unsafeAllowNativeLocalExec as the primary solution.
  • That flag remains an intentional escape hatch for Cursor-native local exec; the default path should remain the Codex bridge, but without false "blocked" UX.

Environment (redacted)

  • Host: Windows
  • Client: Codex Desktop + OpenCodex Cursor provider path
  • Model family: cursor/*
  • Codex sandbox already full-access
  • Issue filing account is a fork collaborator account; no local paths / tokens / private IDs included

Activity

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions