Skip to content

[Bug] Vertex replay session id uses promptCacheKey, which is shared across conversations #1312

Description

@lidge-jun

Client or integration

Codex CLI

Area

Provider adapter

Summary

vertexReplaySessionId() (src/adapters/google.ts:56) keys the Vertex thought-signature replay namespace on parsed.options.promptCacheKey, under a comment that says it does something else:

/** Prefer Codex's stable opaque thread key; retain the existing deterministic fallback for clients
 * that omit it. ... */
function vertexReplaySessionId(parsed: OcxParsedRequest): string {
  const promptCacheKey = parsed.options.promptCacheKey?.trim();
  return promptCacheKey || antigravitySessionId(parsed);
}

promptCacheKey is not a thread key. It is the client-supplied Responses prompt_cache_key, accepted as any string (src/responses/schema.ts, copied at src/responses/parser.ts:661), and this repository elsewhere treats it as explicitly shared across conversations:

  • src/adapters/cursor/request-builder.ts:227 warns against using a shared prompt_cache_key as a conversation id;
  • Claude Desktop cache cohorts are marked as shared in src/server/responses/core.ts:620 and src/server/claude-messages.ts:701.

So two distinct conversations in the same cache cohort share a Vertex replay namespace, and any client can choose the value.

Relationship to #1297

This is the same class of defect #1297 reported for the Cloud Code Assist path, on a different anchor. #1311 fixed the CCA side by anchoring on _clientThreadId and deliberately not on promptCacheKey; it left this one alone rather than bundling an unrelated path into that fix.

Worth recording how it surfaced: while fixing #1297 I found this function and read its comment as the correct pattern to copy. It is not — the comment describes the right anchor and the code uses a different one. Anyone reading google.ts for guidance will make the same mistake.

Severity

Lower than #1297, and the two failure modes differ in kind:

Sharing is partly mitigated the same way the original CCA comment argued: the replay cache keys signatures on functionCall identity (name + args), so a shared namespace does not by itself misattribute a signature. That mitigation is real but it is not a reason for the anchor to be wrong, and it does not cover a client that chooses the value deliberately.

Suggested fix

Mirror #1311: prefer parsed._clientThreadId (populated from x-codex-parent-thread-id at src/server/responses/core.ts:1413), fall back to the existing deterministic id. Unlike the CCA case this value never leaves the process — it scopes a local replay store rather than going on the wire — so the change carries no provider-visible risk.

If promptCacheKey is kept for some reason I have not seen, the comment should at least stop claiming it is a thread key.

Version

dev at b5d44a534.

Operating system

Not platform-specific.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliCLI, config inject, packaging flagsplatformOS/service/tray/ACL (Windows-heavy, not Windows-only)providerProvider adapters, OpenAI-compat presets, upstream API quirks

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions