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

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