Skip to content

Cursor ref-less checkpoint lookup can reuse another conversation's state #2559

Description

@luvs01

Client or integration

Codex App and other Responses clients using the Cursor provider adapter

Area

Provider adapter

Summary

On current dev (e1fb6755951c82fc0fc137820d2b40208d79e918), a request without an explicit checkpointRef can reuse a live Cursor checkpoint from a different conversation.

getCursorCheckpointForPrefix(...) requires a unique prefix digest and matches the system digest, covered-message count, credential identity scope, and model affinity. It does not match conversationId. resolveCursorCheckpoint(...) then enforces conversation equality only when an explicit ref exists.

At the same time, resolveCursorConversationId(...) generates a fresh provider conversation ID when neither _cursorConversationId nor a stable client-thread owner is available. The generated conversation can therefore import the sole matching checkpoint from another conversation.

The checkpoint is provider conversation state rather than a content-addressed prompt cache. Reusing it can carry prior conversation structure, summaries, tool/subagent state, and file-related state into an unrelated request.

Expected safety boundary:

  • An explicit checkpoint ref keeps the existing conversation, identity, model, lineage, and health checks.
  • Ref-less prefix lookup is allowed only when the request already has a stable owner: a remembered _cursorConversationId, a non-empty parent _clientThreadId, or the existing bounded process-local HMAC derived from the complete Desktop session-id and thread-id pair.
  • The selected snapshot must match the resolved request conversationId.
  • A ref-less request with no stable owner fails closed to full replay; content-prefix uniqueness alone is not ownership authority.
  • Isolated helper turns do not reuse parent or sibling checkpoints.
  • The Desktop fallback is Cursor-only: it does not widen Responses replay scope or persist raw headers.

This is the still-applicable first P1 finding left on merged PR #2277: #2277 (comment)

Reproduction

  1. Under one Cursor credential scope and model, complete conversation A whose first user message has a unique prefix, then commit its ConversationStateStructure checkpoint.
  2. Start unrelated conversation B without a continuation ref or stable client-thread identity.
  3. Give B a history beginning with the same user prefix plus a later suffix.
  4. Observe B enter checkpoint mode with A's checkpoint bytes even though B has a different generated conversationId.

Regression coverage for the fix should:

  • reject a unique matching prefix from a different conversation;
  • preserve ref-less reuse for stable _cursorConversationId, parent-thread, and bounded Desktop session/thread owners;
  • preserve forced-fresh recovery with the Desktop owner;
  • select the owned snapshot when multiple conversations share one prefix;
  • avoid refreshing TTL/LRU for unrelated same-prefix snapshots;
  • full-replay when no stable owner exists; and
  • preserve explicit-ref behavior and helper isolation.

Version

dev at e1fb675

Operating system

Cross-platform adapter logic; reproduced in source-level tests on Windows 11

Provider and model

Cursor / gpt-5.6-sol (the ownership bug is model-independent)

Logs or error output

No runtime error is emitted. The incorrect state reuse is observable through continuationMode=checkpoint and checkpoint bytes belonging to another conversation.

Screenshots and supporting files

No screenshot is required for this non-GUI state-isolation defect.

Redacted configuration

{
  "provider": "cursor",
  "credentialScope": "same-account",
  "checkpointRef": null,
  "stableClientThreadOwner": null
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglanded-via-maintainerOriginal PR closed after landing via a maintainer merge trainproviderProvider adapters, OpenAI-compat presets, upstream API quirks

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions