Claude’s Memory Heist: The Read-Only Browser That Wrote Secrets Into URLs
Site Owner
发布于 2026-07-19
A patched Claude web-fetch exploit turned permitted link navigation into a covert output channel. This case study shows how data provenance, capability separation, and egress policies can prevent browser agents from leaking private context.
Claude’s Memory Heist: The Read-Only Browser That Wrote Secrets Into URLs
On July 9, 2026, security researcher Ayush Paul published a Claude conversation that looked harmless. By the time Claude finished answering, an attacker-controlled server had received Paul’s full name, current employer, hometown, and answers to security questions. The chat showed no warning that personal data had left the session (Ayush Paul, “The Memory Heist”).
Six days later, Simon Willison reconstructed the mechanism. The attacker used Claude’s own web-browsing rules to turn permitted link navigation into an exfiltration channel. Anthropic subsequently closed that specific route, according to Willison (Simon Willison, July 15, 2026).
The patch matters. The design error matters more.
Any agent that can place secret-derived bytes into a network request has a write channel, whatever the tool is named.
A browser request became a covert output
Claude’s everyday assistant can use stored summaries of recent conversations and search older conversation history when needed. Paul paired that private context with two built-in browsing tools: web_search and web_fetch (Paul’s first-party account).
#Anthropic#Claude#AI Agent#AI工程
A direct attack failed. When Paul asked Claude to construct a URL containing his name and visit it, web_fetch rejected the request. Anthropic had already restricted which destinations the tool could reach.
The restriction allowed three URL sources. A destination could come directly from the user, appear in web_search results, or appear as a link inside an earlier web_fetch response. That last permission enabled ordinary browsing: fetch a page, find a relevant link, follow it.
It also delegated destination authority to the page author.
Paul’s malicious site offered Claude an alphabet of links. The injected instructions framed those links as an authentication flow and asked the assistant to find personal details one character at a time. Each selected path disclosed another character to the attacker’s server. The server did not need a POST body, file upload, or shell command. Its access logs were enough (technical walkthrough).
The page also inspected the request’s user agent. It served the malicious instructions to Claude-User, which reduced the chance that an ordinary browser visit would reveal the attack. Willison highlighted this selective delivery in his independent summary (Willison).
That detail should bother anyone who debugs an agent by opening the same page in Chrome. A server can show the developer a clean page and send the agent a hostile one. Screenshots from a human browser do not prove what the agent received.
Anthropic’s reported fix removed web_fetch’s permission to navigate to additional links returned within fetched content. The company told Paul it had identified the issue internally, and it did not pay a bounty, according to the two public accounts (Paul; Willison). This article does not claim the closed route still works.
“Read-only” describes intent, not information flow
HTTP GET is conventionally read-only because the client asks a server to return a resource. Security teams often import that application-level label into capability design: a fetch tool reads, while a POST tool writes.
The network sees a broader transaction. Every GET reveals a destination, path, query string, headers, and timing. A remote server can record all of them. Place private data in any observable field and a read operation becomes an outbound message.
A read-only browser agent resembles a clerk who cannot mail a parcel but can type any string into a courier’s tracking form. The parcel remains in the warehouse. The tracking service still receives whatever the clerk typed.
This failure pattern crosses vendors. In May 2026, a separate Microsoft Copilot Cowork finding used external images as the outbound channel. A prompt injection could cause the agent to send messages containing attacker-controlled image references; opening the message triggered network requests. Pre-authenticated OneDrive download links raised the impact because disclosure of the URL could disclose the underlying file (Simon Willison’s report).
The two incidents used different products and interfaces. Both crossed the same boundary: untrusted content influenced a network-visible value while the agent could access private data.
Content filters look for forbidden prose. They often miss a URL path assembled one character at a time, an image source carrying a token, or a redirect whose destination encodes a document identifier. The harmful output may never appear as a sentence.
The security property we need is controlled egress, not a read-only verb.
The model cannot enforce this boundary alone
Prompt injection exploits a basic ambiguity. Models receive instructions and data as token sequences, then infer which role each sequence should play. Attackers craft data that resembles privileged instructions.
Research summarized by Willison in June 2026 demonstrates how fragile that inference can be. Text styled like a model’s internal reasoning produced an average attack success rate of 61% in the cited dataset. Rewriting the same content so it looked less privileged reduced the rate to 10%. The researchers call the mechanism “role confusion” (“Prompt Injection as Role Confusion”).
Those figures do not measure every model or deployment. They show that formatting can materially change a model’s perception of authority even when the meaning stays similar.
A system prompt that says “never reveal secrets” can still help. It cannot serve as the only egress control. The same model interprets the hostile page, chooses a tool, and judges whether its own request is safe. One compromised decision can defeat the whole arrangement.
OpenAI’s published guidance follows an architecture-first direction: constrain risky actions and protect sensitive data within agent workflows (OpenAI, “Designing AI agents to resist prompt injection”). The workflow must remain safe when the planner occasionally misclassifies an instruction.
That requirement changes the engineering question. Instead of asking whether the model intended to leak a value, ask whether any data derived from a sensitive source can reach an untrusted destination.
Add provenance to every outbound request
Most tool frameworks attach permissions to actions. An agent may call web_fetch, or it may not. That binary model ignores where request data came from and who authorized the destination.
A useful egress policy evaluates both dimensions.
Data provenance can start with a small set of labels:
Public: page text, public documentation, open search results.
Session: values supplied by the user for the current task.
User-approved: the user supplied or explicitly confirmed the exact origin.
Search-discovered: a search provider returned the destination.
Content-discovered: an untrusted page supplied the link.
Generated: the model or code assembled the destination dynamically.
The labels produce a compact policy matrix:
Data in request
User-approved
Search-discovered
Content-discovered
Generated
Public
Allow
Allow
Allow with limits
Allow with limits
Session
Allow for stated task
Review
Review
Review
Private
Review
Deny by default
Deny
Deny
Secret
Deny
Deny
Deny
Deny
Teams will tune the cells for their product. The important move is preserving both labels until the request crosses the network boundary.
A URL derived from a fetched page should retain the content-discovered label. If the model appends a value retrieved from memory, that path segment should retain the private label. The final request inherits the strictest combination.
This is taint tracking for agent workflows. It does not require understanding the attacker’s prose. It observes that private bytes are about to reach a destination authorized only by untrusted content and blocks the request.
Separate capabilities that are currently bundled
“Browsing” usually hides several authorities behind one tool name. Search queries a provider. Fetch retrieves a known URL. Link following lets a remote page select the next destination. Redirect following lets an intermediate server change it again.
Treat those as separate capabilities.
An agent may need search and fetch for a research task without needing autonomous link following. A documentation crawler may need same-origin links while refusing cross-origin navigation. A shopping assistant may follow merchant links but require approval before opening a newly registered domain.
Canonicalize the destination immediately before connection. Policy checks performed during planning can become stale after URL parsing, DNS resolution, or redirects. Normalize the scheme, host, port, path, and encoded characters. Apply the rule again to every redirect target. Block credentials in URLs and reject confusing host representations.
Limit what a fetched page may contribute. Same-origin navigation with a short, normalized path has a different risk profile from a cross-origin link containing high-entropy query values. Entropy is only a signal—legitimate signed URLs can look random—so use it to trigger review or combine it with provenance. Do not present it as proof of theft.
Keep the request builder outside the model. Give the planner structured fields such as resource_id or page_number, then let trusted code construct the URL from an approved template. Free-form URL generation gives the model a convenient encoder.
Reduce the amount of private context at risk
Paul’s case became serious because browsing and memory met in one planning context. Many web tasks need no long-term memory. A request to summarize a public page should run without private conversation history, internal files, or environment secrets.
Load private context only when the task calls for it. If the user asks to compare a page with last week’s discussion, make that composition explicit. The interface can show which private sources will enter the run and which network tools remain available.
For higher-risk workflows, use two processes. A browsing worker handles untrusted pages without private context. A separate trusted component receives a constrained summary and performs the comparison. The boundary should pass data, not instructions or arbitrary URLs.
Human approval belongs at trust-boundary expansion. Repeated confirmation for every fetch trains users to click through warnings. Ask when a request combines newly discovered destinations with private-derived values, crosses origins after a redirect, or invokes a destination class the user has not approved.
Log the derivation, not only the tool call
A conventional trace might record web_fetch(url). That proves what happened and hides why the URL had that value.
An incident-ready trace records the destination’s authority label, the sources that contributed to each field, transformations applied to those sources, redirect history, and the policy rule that allowed or denied the request. Sensitive values can be hashed or referenced by internal IDs rather than copied into logs.
Derivation logs answer the questions that matter after a near miss. Did a path segment come from public page text or private memory? Did the model generate it, copy it, or encode it? Which policy cell approved the crossing?
Without that chain, teams can count requests while remaining blind to the leak path.
Three checks to run this week
Trace outbound values to their sources. Pick real agent sessions and determine whether every URL component can be tied to public, session, private, or secret data. Unknown provenance should fail closed for untrusted destinations.
Split fetch from navigation. Give known-URL retrieval, content-discovered link following, and redirect following separate permissions. Re-check the final destination at the network boundary.
Test exfiltration, not just bad language. Plant canary values in memory and hostile instructions in pages, documents, and tool results. Verify that no request path, query, header, image reference, or redirect carries the canary outside its approved boundary.
Anthropic closed the link-following route described here. Other routes will appear wherever private context and attacker-influenced egress share the same planner.
A tool name cannot make that composition safe. If secret-derived bytes can reach the network, the agent can write.