Fix Claude CLI session lifecycle continuity#70106
Conversation
🔒 Aisle Security AnalysisWe found 2 potential security issue(s) in this PR:
1. 🟡 Implicit daily session expiry bypass for provider-owned CLI sessions can cause indefinite sensitive state retention
DescriptionIn
Vulnerable logic: const skipImplicitExpiry = hasProviderOwnedSession(entry) && resetPolicy.configured !== true;
const entryFreshness = entry
? isSystemEvent || skipImplicitExpiry
? ({ fresh: true } satisfies SessionFreshness)
: evaluateSessionFreshness({ updatedAt: entry.updatedAt, now, policy: resetPolicy })
: undefined;
RecommendationDo not disable the implicit daily expiry for provider-owned CLI sessions by default. Options:
Example approach (preserve binding while resetting rest): const cliBinding = provider ? getCliSessionBinding(entry, provider) : undefined;
const entryFreshness = entry
? isSystemEvent
? ({ fresh: true } satisfies SessionFreshness)
: evaluateSessionFreshness({ updatedAt: entry.updatedAt, now, policy: resetPolicy })
: undefined;
// if stale daily but provider-owned, roll session but reattach cli binding to new entry
if (entry && cliBinding && entryFreshness?.dailyResetAt && entry.updatedAt < entryFreshness.dailyResetAt) {
// proceed with rollover, but copy cliBinding into the new session entry
}Also document and/or make this behavior an explicit config flag (opt-in) to avoid surprising data retention changes. 2. 🟡 Gateway session APIs may expose provider-owned CLI session binding metadata (cliSessionBindings) to clients
DescriptionThe gateway now persists Because gateway session endpoints (e.g.,
Vulnerable change (persistence/enabling propagation): cliSessionIds: entry?.cliSessionIds,
cliSessionBindings: entry?.cliSessionBindings,
claudeCliSessionId: entry?.claudeCliSessionId,If the gateway is used in a multi-client or multi-tenant context (or if less-trusted clients can connect), this can leak identifiers that link a user/session to a specific provider account/profile and may aid session correlation or other abuse. RecommendationTreat
Example: strip before returning function sanitizeSessionEntryForClient(entry: SessionEntry): SessionEntry {
const { cliSessionBindings, ...rest } = entry;
return rest;
}Additionally:
Analyzed PR: #70106 at commit Last updated on: 2026-04-22T10:05:59Z |
Greptile SummaryThis PR fixes CLI session lifecycle continuity across three dimensions: preventing implicit daily resets from cutting provider-owned CLI sessions, allowing legacy bindings without Confidence Score: 4/5Safe to merge after confirming the downgrade path for mcpResumeHash is intentional or adding a covering test. One P2 gap in the mcpResumeHash src/agents/cli-session.ts — the downgrade direction of the mcpResumeHash fallback (stored has hash, current client does not) deserves a test or an explicit comment justifying the behavior.
|
4dca716 to
42777c7
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42777c79d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| groupChannel: resolvedGroupChannel ?? entry?.groupChannel, | ||
| space: resolvedGroupSpace ?? entry?.space, | ||
| cliSessionIds: entry?.cliSessionIds, | ||
| cliSessionBindings: entry?.cliSessionBindings, |
There was a problem hiding this comment.
Avoid overwriting newer CLI binding metadata
nextEntryPatch copies entry?.cliSessionBindings before updateSessionStore(...) re-reads the store, so overlapping requests for the same session can lose newer binding metadata: a concurrent writer can update cliSessionBindings in the locked store snapshot, then this stale patch value overwrites it during mergeSessionEntry. That drops newer auth/MCP hashes and can cause avoidable CLI session invalidations on subsequent turns. Read/preserve this field from the in-lock store[primaryKey] instead of the pre-lock entry snapshot.
Useful? React with 👍 / 👎.
Summary
/resetand configured reset policies.mcpResumeHashupgrade via existingmcpConfigHashchecks.cliSessionBindingswhen gateway agent requests refresh session state.Tests
pnpm test src/agents/cli-session.test.ts src/auto-reply/reply/session.test.ts src/gateway/server.agent.gateway-server-agent-b.test.tspnpm check:changedpnpm exec oxfmt --check docs/concepts/session.md docs/gateway/cli-backends.md src/agents/cli-session.test.ts src/agents/cli-session.ts src/auto-reply/reply/session.test.ts src/auto-reply/reply/session.ts src/config/sessions/reset-policy.ts src/gateway/server-methods/agent.ts src/gateway/server.agent.gateway-server-agent-b.test.ts