Cursor Composer leaked tab context between projectsWhat happened. What to check.
A fintech developer saw a Stripe key from Project A appear in a Cursor diff suggestion for Project B. The key was real. The second project had never touched it. Here's what happened and what to do about it.
-
01
Trigger
Two projects, one window
Composer shares process state across open workspace tabs
same session · same LLM call -
02
Vector
Context window pollution
Open files from Project A included in Project B prompt
secrets in open tabs -
03
Exposure
Diff suggestion reveals key
Stripe key from Project A appears in Project B suggestion
visible in Composer output
TL;DR· the answer, in twenty seconds
What: Cursor Composer, the multi-file edit mode, inadvertently included open-file context from a second project tab in the same window session when constructing LLM prompts. Developers using Cursor with two or more projects open simultaneously could see content from Project A surface in Composer suggestions for Project B.
Fix: Update Cursor to the late-April 2026 release (check Cursor > About or run cursor --version from a terminal). Then audit your Cursor session history: open ~/.cursor/logs/ and check for prompt files that reference multiple workspace roots.
Lesson: Cross-project context bleed is a structural risk of any IDE-integrated agent that shares a process across workspaces. The one-window-one-project discipline is not paranoia; it's the only way to guarantee isolation today.
A developer at a fintech was working across two repos in a single Cursor window in mid-April 2026. Project A was a backend service with Stripe integration. Project B was a separate internal tool with no payment code. She asked Cursor Composer to scaffold a new module in Project B. The diff suggestion came back with a STRIPE_SECRET_KEY reference. The value was real. It matched her Project A credentials exactly.
She had not copied the key. She had not referenced Stripe anywhere in Project B. The key arrived because Composer, in constructing its prompt for Project B's edit, included context from the open Project A files sitting in adjacent tabs.
This is not a hypothetical attack. It is a context-assembly bug with real credential exposure as a side effect.
Cursor's changelog documented the fix in late April 2026. The patch narrowed Composer's context collection to the active workspace root. But the window between "bug introduced" and "patch shipped" ran long enough that many developers may have unknowingly generated prompts that crossed project boundaries. If you used Cursor Composer with multiple projects open between roughly March and late April 2026, you have an audit to run.
What to know in 60 seconds
- Cursor Composer constructs LLM prompts that include file context. The bug caused it to pull context from all open tabs in the window session, regardless of which project those tabs belonged to.
- Any file open in Tab B could contribute text to a Composer prompt for Tab A's project. That includes
.envfiles, config files with embedded credentials, and any file the developer had open for reference. - The exposure is one-directional in the prompt, but bidirectional across time: Project A could bleed into Project B and vice versa depending on which project was "active" when Composer ran.
- Cursor patched the bug in late April 2026. Updating is the first step.
- The audit window is your Cursor session history. Composer saves prompt context locally. You can inspect what got included.
How Composer builds its context
Understanding the bug requires a brief detour into how Composer works.
Composer is Cursor's multi-file edit mode. You describe a change, Composer reasons about which files to read and modify, and it submits a prompt to the underlying model that includes the contents of relevant files, the active cursor position, and surrounding code. That context assembly runs inside the Cursor process.
The process hosts all open tabs in the window. In normal single-project use, that is fine: all tabs belong to one workspace root and Composer's context collection stays bounded. The bug appeared when a developer opened a second project via "Add Folder to Workspace" or by opening a second workspace tab. The context collector did not enforce a workspace-root filter. It gathered recently-accessed file contents across all open workspaces.
Knostic's research blog covers the general pattern of IDE-integrated agents overreading their environment. The mechanism here is different from the settings.local.json env-var capture they documented for Claude Code in February 2026, but the root cause family is the same: an agent that builds prompts from ambient state rather than explicitly scoped state will eventually include something it should not.
What got exposed
The realistic exposure surface depends on what you had open.
Any file open in a browser tab or editor pane in Cursor during a Composer session was a candidate for inclusion. The highest-risk categories:
.envfiles left open after editing- Config files with API keys or database connection strings
- Credential files for test fixtures or staging environments
- Any file containing a token that was open "for reference" while working in the adjacent project
The exposure does not require the file to be staged or committed. An unsaved .env open in an editor tab was sufficient. The content was in memory, and Composer's context collector found it.
GitGuardian's 2026 State of Secrets Sprawl tracks AI-assisted commits leaking secrets at roughly 2x the baseline rate. This incident fits a related but distinct pattern: the agent reads credentials before the commit stage, during prompt construction, and the exposure happens in the LLM call rather than in the git history.
Update first, then audit
Step 1: Update Cursor.
Open Cursor, go to Cursor > About Cursor, and check the version. The patch landed in the late-April 2026 update. If you are behind that release, update before doing anything else. On macOS, cursor --version in a terminal gives you the same information.
Step 2: Find your Composer prompt logs.
Cursor saves Composer session context locally. The path varies by platform, but on macOS:
ls -la ~/Library/Application\ Support/Cursor/logs/
Look for files named with a timestamp from March through late April 2026. The prompt context files contain the assembled input to the model. Search them:
grep -r "STRIPE\|sk_live\|DATABASE_URL\|api_key\|API_KEY\|secret" \
~/Library/Application\ Support/Cursor/logs/
Adjust the pattern for your actual credential types. If you work with AWS, add AKIA to the pattern. If you use Anthropic keys, add sk-ant. Be specific enough to avoid noise, broad enough to catch variants.
Step 3: Check which workspace roots appear in the same log file.
A clean session shows one workspace root per prompt log. A session affected by the bug shows two or more workspace roots in the same file. If you find a prompt log with multiple roots, the contents of both workspace's open files contributed to that prompt.
grep -h "workspaceRoot\|rootPath\|projectRoot" \
~/Library/Application\ Support/Cursor/logs/*.log | sort -u
Multiple distinct paths in a single log file is the signal. One path is normal.
Step 4: For every cross-project prompt log you find, list the secrets visible in that log.
Any secret that appears in a cross-project prompt was transmitted to Cursor's LLM backend as part of that session. Cursor's cloud infrastructure received it. Depending on your Cursor privacy settings and whether the model was a hosted API or a local model, that data may have been logged server-side.
Rotate any secret that shows up. The rotation scope is the credential itself, not just the file. Deleting the .env entry does not invalidate a token that was already transmitted.
The session habits that made this worse
The bug required two projects open in one window. That is an extremely common workflow for developers who maintain related services, who context-switch between a frontend and backend, or who use Cursor's "Add Folder to Workspace" to keep utilities at hand.
The Register's coverage of AI tooling incidents tracks a recurring theme: the workflow that feels natural is often the one that exposes the most state. Opening multiple projects in one window is faster than managing multiple Cursor instances. It feels like a harmless convenience.
The credential risk compounds with specific habits:
Keeping .env files open as reference tabs. Developers do this when they need to copy values during setup. An open .env in one project's tab was available to Composer running in the adjacent project's tab.
Using "Add Folder to Workspace" for shared tooling. A credentials config folder added as a workspace companion for easy access exposes all its open files to Composer sessions in the main project.
Running Composer with a broad file context request ("edit all files related to authentication"). Broader context requests cast a wider net. With the bug present, that net crossed workspace boundaries.
What gets missed in the incident framing
Most post-incident coverage focuses on patching and moving on. Two things are getting missed.
The patch fixed this bug; it does not prevent the next one. Composer's context assembly is a complex piece of code. It runs across every LLM call. The surface area for context-boundary errors is large, and this was not an obviously malicious design choice. It was an engineering oversight. Similar oversights will happen again in Cursor and in every other IDE-integrated agent that does context assembly at call time. The patch history of Cursor's changelog shows active iteration on context quality, which means active iteration on a component that, when wrong, leaks data.
The multi-project window pattern is still the default. Nothing in Cursor today enforces single-project isolation as a mode. You can absolutely open two projects in one window right now on a patched Cursor. The isolation depends on the implementation being correct. That is a software correctness guarantee, not a structural isolation guarantee.
Structural isolation means the two projects cannot share a process boundary. Different Cursor windows satisfy this. Different user accounts satisfy it with more overhead. OS-level sandboxing per project workspace satisfies it most thoroughly.
If secrets are kept in a broker like hasp rather than in .env files, the cross-project bleed changes character. Composer's context collector grabs the open tab, but the tab contains a reference stub, not the live key. The Stripe key that appeared in the Project B diff suggestion would have been a placeholder the model could not use.
Prevent recurrence
The short answer: one project per Cursor window.
The longer answer, for teams that want a defensible policy:
## Cursor multi-project isolation checklist
- [ ] Updated to post-late-April 2026 Cursor release
- [ ] Audited ~/Library/Application Support/Cursor/logs/ for cross-project prompts
- [ ] Rotated any secrets found in cross-project prompt logs
- [ ] Cursor Privacy Mode enabled (Settings > General > Privacy Mode > Enabled)
- [ ] .env files closed (not just saved) before switching project context
- [ ] One project per Cursor window policy documented for team
- [ ] Pre-session habit: close all tabs from previous project before opening new one
- [ ] High-sensitivity projects (prod keys, customer data) run in a dedicated OS user account
- [ ] CI/CD pipeline secrets never appear in local .env files checked by Cursor
- [ ] gitguardian-research or trufflehog pre-commit hook covers all repos touched in Cursor
The Privacy Mode item matters: in Privacy Mode, Cursor does not retain prompt content on its servers. For the April incident, this limits server-side exposure of cross-project content. It does not prevent the content from being transmitted in the first place, but it reduces the retention window.
For the highest-sensitivity work, an OS-level user account per project provides the strongest isolation. Cursor sessions under different accounts cannot share in-process state. The overhead is real. So is the isolation.
What this means for your stack
The Cursor bug is patched. The category it represents is not. Any IDE-integrated agent that does context assembly at call time and shares a process across open projects has a version of this attack surface. The question is whether the current implementation has this specific bug. That is a correctness guarantee that depends on the vendor's code, changes with every update, and fails silently when wrong.
The structural fix is to keep secrets out of the files the agent can read. Credentials that live in a process-scoped vault, injected at execution time and removed when the process exits, are not in any .env file, not in any open tab, and not in any context-assembly path.
hasp is one working implementation. curl -fsSL https://gethasp.com/install.sh | sh, hasp setup, connect a project, hand the next session a reference instead of a key. Source-available (FCL-1.0), local-first, macOS and Linux, no account.
The durable lesson: every IDE-integrated agent is a context vacuum. It pulls from your environment to do its job. If your environment contains secrets, those secrets are in the pull zone. The only reliable fix is to keep secrets out of the pull zone entirely.
Sources· cited above, in one place
- Cursor Changelog and security notes
- Knostic Research on AI code editor secret leakage (Claude Code, Cursor)
- GitGuardian Labs Secrets-in-code research blog
- The Register Coverage of .claudeignore partial-bypass and agent-tooling incidents
- Anthropic Security advisories and Claude Code release notes
- GitGuardian State of Secrets Sprawl report
Stop handing the agent your real keys.
hasp keeps secrets in one local encrypted vault, brokers them into the child process at exec, and never lets the agent read the value.
- Local, encrypted vault — no account, no cloud, no telemetry by default.
- Brokered run — agent gets a reference, the child process gets the value.
- Pre-commit + pre-push hooks catch managed values before they ship.
- Append-only HMAC audit log answers "did the agent touch the prod token?" in seconds.
macOS & Linux. Source-available (FCL-1.0, converts to Apache 2.0). No account.