Cowork: mcp__workspace__bash and web_fetch permanently denied — host passes Bash/WebFetch in --disallowedTools, which aliases onto the workspace tools
Summary
In Cowork on Claude Desktop for Windows, every call to mcp__workspace__bash and mcp__workspace__web_fetch is denied, in every session, permanently. No other tool is affected.
The cause is visible in the command line the desktop host uses to spawn the Claude Code child: it puts mcp__workspace__bash in --allowedTools and Bash + WebFetch in --disallowedTools in the same spawn. The SDK expands those two built-in names onto their workspace equivalents, so the deny list cancels the allow list. Deny outranks allow, and the call is refused by rule.
The apparent intent is to stop Cowork using the local shell so execution goes through the workspace sandbox. The alias expansion carries the denial onto the sandbox tools as well.
Environment
Claude Desktop : 1.44121.1.0 (MSIX, Windows 11 Pro 10.0.26200)
Bundled CLI : claude-code 2.1.258
Plan : personal account, no organization
Permission mode: auto (also reproduced under bypassPermissions)
Evidence
1. The spawned child's command line (captured from Win32_Process, abridged; paths and identifiers redacted):
claude-code\2.1.258\claude.exe
--allowedTools Task,…,mcp__cowork__present_files,…,mcp__workspace__bash
--disallowedTools Bash,PowerShell,NotebookEdit,REPL,JavaScript,WebFetch
--permission-mode auto
--allow-dangerously-skip-permissions
--setting-sources=user
mcp__workspace__bash is allowed and Bash is denied, on the same line.
2. The alias map, in app.asar and in the CLI binary:
{ Bash: "mcp__workspace__bash", WebFetch: "mcp__workspace__web_fetch" }
with an expander that, for each built-in name present in a set, adds the workspace tool id to that set. Applied to the deny set, denying Bash also denies mcp__workspace__bash.
Note mcp__workspace__web_fetch is not in --allowedTools at all, yet is denied identically — consistent with expansion of WebFetch, and not with a hand-written rule.
3. The session's audit record:
{"type":"system","subtype":"permission_denied",
"tool_name":"mcp__workspace__bash",
"decision_reason_type":"rule",
"message":"Permission to use mcp__workspace__bash has been denied."}
with "non_execution_kind":"permission-rule" on the tool result. It is a rule decision, not a declined prompt — no approval dialog is ever raised.
4. The workspace MCP server is healthy — mcpServerStatus reports {"name":"workspace","status":"connected","toolCount":2}, and both tools appear in the session's tool list (197 tools). They are provisioned and refused at call time.
Reproduction
- Cowork session on Claude Desktop 1.44121.1.0 (Windows).
- Ask it to run any shell command.
Error: Permission to use mcp__workspace__bash has been denied.
To see the cause, poll for the child process while sending a message — it lives only for the turn:
$deadline=(Get-Date).AddMinutes(3); $seen=@{}
while((Get-Date) -lt $deadline){
Get-CimInstance Win32_Process -Filter "Name='claude.exe'" |
Where-Object { $_.ExecutablePath -like '*Roaming\Claude\claude-code*' -and -not $seen[$_.ProcessId] } |
ForEach-Object { $seen[$_.ProcessId]=$true; $_.CommandLine }
Start-Sleep -Milliseconds 150
}
Expected vs actual
Expected: mcp__workspace__bash and mcp__workspace__web_fetch run in the workspace sandbox. Denying the local Bash/WebFetch built-ins should not affect them.
Actual: both are denied by rule, permanently, with no user-visible cause.
Why the usual remedies do not apply
A deny rule outranks all of these; each was tried and failed:
- Starting new conversations, and quitting/relaunching the app
- Signing out and back in
- Changing permission mode, including "skip all approvals" (
bypassPermissions) — the argv already carries--allow-dangerously-skip-permissionsand the call is still denied - Editing
~/.claude/settings.json— Cowork does not read it;CLAUDE_CONFIG_DIRpoints at a per-session directory - Every on-device policy source is empty: user/project/local settings,
C:\ProgramData\ClaudeCode\managed-settings.json,HKLM/HKCUpolicy keys, MDM (device is unmanaged), andmcp-user-tool-toggles.json(no workspace entry)
The desktop host's own tool-disabling code paths all log when they run, and none of them fired — so the --disallowedTools list is being assembled somewhere that does not log.
Scope
- Cloud Cowork sessions are unaffected — in a browser session the tools are the plain
Bash/WebFetchbuilt-ins, both work, andmcp__workspace__bashdoes not exist. The account and code-execution capability are fine. - Claude Code outside Cowork on the same machine has a working
Bash. - File, browser and subagent tools in desktop Cowork are unaffected.
Regression note
The bundled CLI 2.1.255 (previous version, still on disk) contains the same alias map, so the expander is not new. The change appears to be host-side — Claude Desktop newly passing Bash and WebFetch in --disallowedTools. On this machine the tools worked in every session before the 1.44121.1.0 update and in none since.
Suggested fix
Exclude the workspace tool ids from alias expansion when building the deny set, or stop passing Bash/WebFetch in --disallowedTools when the workspace equivalents are being granted. At minimum, an explicit entry in --allowedTools should not be silently overridden by an aliased deny derived from a different tool name.