[BUG] Artifact tool cannot read live artifacts in Cowork — read path binds to native WebFetch, which Cowork substitutes with mcp__workspace__web_fetch
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
In a Cowork session, the Artifact tool cannot read an existing artifact that the session did not
itself create. Because publishing to such an artifact requires reading the live version first, the
publish is refused as well — every push needs force: true.
The refusal blames "your WebFetch deny rule (WebFetch)". No such rule exists. I checked
~/.claude/settings.json (no permissions block), settings.local.json (absent), ~/.claude.json (zero
WebFetch matches), managed-settings.json (absent), the project .claude directory (absent), and the
Cowork session's own .claude/settings.json (contains {}). The error sends users hunting for a
configuration that isn't there — that misdirection cost me more time than the bug itself.
The actual cause is that Cowork sandboxes host-executing tools: it withdraws native Bash and
WebFetch and substitutes mcp__workspace__bash and mcp__workspace__web_fetch. The Artifact tool is
still wired to native WebFetch, which no longer exists in the session.
What Should Happen?
The Artifact tool should read the live artifact via the fetch capability Cowork actually provides
(mcp__workspace__web_fetch), and the publish should proceed normally without force: true — the same
way it works on the Claude Code surface, where native WebFetch is present.
Separately: when a tool genuinely is unavailable, the error should not attribute it to a user
-configured deny rule that does not exist.
Error Messages/Logs
You haven't viewed the latest version of this artifact, so nothing was published. The live content
was withheld here by your WebFetch deny rule (WebFetch), which also blocks re-reading this
artifact — tell the user rather than working around it; do not resend your previous content
unchanged. force:true discards that newer version — someone's save from the page itself, or
another session's publish — so use it only when the user explicitly asks to overwrite.
Steps to Reproduce
- Publish an HTML file as an artifact from a Cowork session, so the account owns it. Note its URL.
(Or use any artifact the account already owns.)
- Start a NEW Cowork session with a local folder connected.
- Ask Claude to read that artifact:
Artifact(action: "read", url: "https://claude.ai/code/artifact/<artifact-uuid>")
-> refused, with the error above.
- Ask Claude to publish an edited local file to the same URL:
Artifact(file_path: "<local .html>", url: "https://claude.ai/code/artifact/<artifact-uuid>")
-> also refused, because publishing requires the read in step 3.
- Retry step 4 with force: true -> succeeds.
Step 2 matters: a session that CREATED the artifact can publish to it without a read, so the bug is
invisible until a later session tries to update it.
Contrast case that isolates the cause: run step 3 from the Claude Code surface instead of Cowork,
where native WebFetch is present. The read succeeds and returns the full file.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude desktop app 1.49585.0 (Cowork surface) — prod build, commit timestamp 2026-09-08. Not the npm CLI.
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
SURFACE NOTE
This is the Claude desktop app's Cowork surface, not the npm CLI, so "Claude Code Version" and
"Terminal/Shell" don't map cleanly. Filing here because Artifact is a Claude Code tool and Cowork
embeds the harness. Redirect me if another tracker is correct.
ROOT CAUSE
In Claude.app/Contents/Resources/app.asar:
var FFt = ["Bash","PowerShell","NotebookEdit","REPL","JavaScript","WebFetch"]
That is Cowork's disallow list for host-executing tools, each replaced by a VM-routed MCP
equivalent. There is also a conditional path appending "WebFetch" to disallowedTools, gated on a
feature flag coworkWebFetchViaApi (key 1978029737).
Artifact is on Cowork's allowed-tool list, so it loads — but its read path looks for native
WebFetch, doesn't find it, and surfaces that absence as a deny rule.
EVIDENCE — tool occurrences across my own Cowork session transcripts:
Bash 0
WebFetch 0
mcp__workspace__bash 2935
mcp__workspace__web_fetch 1024
WebSearch / Read / Artifact 596 / 414 / 21
Bash and WebFetch are both fully substituted. mcp__workspace__web_fetch has 1024 successful calls
in these sessions, which confirms outbound fetching works — only the Artifact tool's binding is
stale. Artifact itself loads and runs (21 calls); it is specifically the read/verify step that fails.
SUGGESTED FIX
Route the Artifact read/verify path through the substituted capability
(mcp__workspace__web_fetch) rather than native WebFetch. Failing that, correct the error text so it
does not attribute the failure to a user-configured deny rule.
WORKAROUND
Pass force: true on every publish. This is not free: force discards anything edited inside the
artifact since the last push. Users with stateful artifacts must manually export that state and
fold it back into the source file before every single update.
REGRESSION
Answered "I don't know" because I haven't tested older versions, but this looks architectural to
Cowork's sandboxing rather than a recent break. I have no evidence it ever worked from a
non-creating Cowork session.
NOT FULLY TRACED
A secondary policy check in the same code path (reasons "platform_block" / "cache_cleared") never
fired in local telemetry, and I did not resolve it. It doesn't change the outcome: WebFetch is
absent from Cowork sessions either way. Noting it so the finding isn't overstated.
ACCOUNT CONTEXT
Personal Claude Pro, no managed organization and no admin policy involved — so this is not an
enterprise tool-restriction setting.