[BUG] Tool-result references are not project/session isolated (cross-project content leakage)

Resolved 💬 2 comments Opened Jun 5, 2026 by isbcd Closed Jul 11, 2026

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 session rooted in Project A, a Bash tool call (a Python CLI that only prints JSON) rendered, as its result, an unrelated ~86 KB block of Xcode project.pbxproj debug output belonging to a DIFFERENT project (Project B). The same foreign block appeared in two positions of one combined command's output, byte-for-byte identical.

This is cross-project data leakage. The leaked content was also persisted into Project A's own session transcript (because it was rendered as A's output).

Root cause (hypothesis): Claude Code stores large tool results on disk under a three-level path <project>/<session-id>/tool-results/<id>.txt, but the reference/lookup layer addresses them by a single, globally-flat 9-character id with NO project or session component. The isolation boundary exists in storage but is bypassed by addressing. Under --resume, a persisted id resolves via a global lookup and can land on another project's file. Storage isolation ≠ reference isolation.

What Should Happen?

A tool result rendered in Project A's session must resolve ONLY to that session's own tool-result files. Content from another project or session must never surface.

Suggested fix:

Address tool results by a composite key (project, session, id) (or the full three-segment path) through every lookup.
Or scope the id namespace to the session (encode session into the id).
Add a resolution-time guard: reject a tool-result file whose on-disk (project, session) does not match the resolving session.

Error Messages/Logs

No error was raised — the failure is silent (wrong content returned as success). Forensic data:

Re-running the identical command with stdout/stderr redirected to files: clean correct JSON (676 bytes), empty stderr. sys.modules has no module from the other project; ps shows no related process.
Source: <home>/.claude/projects/<Project B>/<session-B>/tool-results/bs4pgt1ey.txt (86 KB)
Not a collision: 23 files, 23 unique ids; bs4pgt1ey exists in one place only.
Flat id namespace: b1plcujfu, b2vmqiu13, b6o8ofgjy, b6rlypd6m, bdshnv4bi …

Steps to Reproduce

Not deterministically reproducible (intermittent, under --resume). Trigger conditions + forensic verification:

Trigger conditions:

Use Claude Code across multiple projects so several tool-results/<id>.txt accumulate.
Resume a session (--resume <session> --replay-user-messages).
Run a command whose output is large enough to spill to a tool-results file.
Intermittently, the result shows another project's tool-result content.
Forensic verification (deterministic):

Redirect the command's stdout/stderr to files => current process output is clean.
grep the foreign text across ~/.claude/projects/ => found in another project's tool-results/<id>.txt.
List all tool-results/*.txt ids => globally unique, no project/session component.
Environment: Claude Code 2.1.161 (desktop, macOS); model claude-opus-4-8; --resume <session-A> --replay-user-messages.

Note: inverse of #65456 (that asks for intentional cross-project handoff; this is unintended leakage).

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.161

Platform

Other

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Platform: Claude Code desktop app (macOS), not a direct API integration. The Platform field above does not have a "Claude Code" option so "Other" was selected.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗