fix(gateway): clear auto-fallback model override on session reset#63155
Conversation
Greptile SummaryThis PR fixes a regression introduced in cb0a752 where Confidence Score: 5/5Safe to merge — targeted one-line conditional guard with no unintended side effects and existing integration test coverage for the preserved path. The fix is minimal and correct. The authProfileOverrideSource type is a closed 'auto' | 'user' union, so the condition exhaustively handles every case. Existing tests in server.sessions.gateway-server-sessions-a.test.ts already cover the 'user' path. No P0 or P1 findings. No files require special attention.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a054e197a
ℹ️ 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".
| ...(currentEntry?.authProfileOverrideSource === "user" | ||
| ? { | ||
| providerOverride: currentEntry?.providerOverride, |
There was a problem hiding this comment.
Preserve explicit model overrides without auth profile source
The new guard only carries providerOverride/modelOverride when authProfileOverrideSource === "user", but explicit user model picks often do not set that field. applyModelOverrideToSessionEntry() clears authProfileOverrideSource whenever no profile override is provided, while still persisting providerOverride and modelOverride (for example from /model or sessions.patch paths), so those user-selected overrides now get dropped on /reset//new and the session incorrectly reverts to defaults.
Useful? React with 👍 / 👎.
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd2e06b257
ℹ️ 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".
| const explicitSelection = fallbackPinnedSelection ?? currentSelection; | ||
| if (explicitSelection && !sameProviderModelRef(explicitSelection, defaultRef)) { | ||
| preserved.providerOverride = explicitSelection.provider; | ||
| preserved.modelOverride = explicitSelection.model; | ||
| } |
There was a problem hiding this comment.
Avoid preserving stale fallback-selected model on reset
This logic can still pin a stale model after config changes: when currentSelection matches fallbackNoticeActiveModel, it rewrites to fallbackNoticeSelectedModel and preserves it if it differs from the current default. In the common sequence “default A falls back to B, user changes config default to C, then /reset”, this keeps an override to old A instead of returning to C, so reset still ignores updated agent config.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 25cfe71aec
ℹ️ 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".
| } | ||
|
|
||
| const preserved: Partial<ResetPreservedSelectionState> = {}; | ||
| if (entry.modelOverrideSource === "user" && entry.modelOverride) { |
There was a problem hiding this comment.
Preserve legacy user model overrides during reset
resolveResetPreservedSelection now keeps model overrides only when modelOverrideSource === "user", but this new field did not exist in previously persisted sessions, so existing user-selected overrides (modelOverride/providerOverride with no source) are treated like auto fallback and dropped on /reset//new. This creates an upgrade regression for users who had explicit model selections before this commit, because their next reset silently reverts to config defaults; please treat missing source as legacy-user (or backfill source before reset) when modelOverride is present.
Useful? React with 👍 / 👎.
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
e0c278b to
7560566
Compare
When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in cb0a752 ("fix: preserve reset session behavior config")
7560566 to
69610fa
Compare
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟠 Policy bypass: legacy sessions without modelOverrideSource are treated as user model overrides during sessions.reset
Description
This is dangerous because older versions could persist
Impact depends on deployment, but in environments where model selection is restricted (allowlist, provider restrictions, cost controls), this can become a model/provider policy bypass. Vulnerable code: const preserveLegacyUserModelOverride =
entry.modelOverrideSource === "user" ||
(entry.modelOverrideSource === undefined && Boolean(entry.modelOverride));
if (preserveLegacyUserModelOverride && entry.modelOverride) {
preserved.providerOverride = entry.providerOverride;
preserved.modelOverride = entry.modelOverride;
preserved.modelOverrideSource = "user";
}RecommendationDo not assume Safer options:
const preserveUserModelOverride = entry.modelOverrideSource === "user";
const looksLikeAutoFallback = Boolean(
entry.fallbackNoticeActiveModel ||
entry.fallbackNoticeSelectedModel ||
entry.fallbackNoticeReason
);
const preserveLegacy = entry.modelOverrideSource === undefined && entry.modelOverride && !looksLikeAutoFallback;
if ((entry.modelOverrideSource === "user" || preserveLegacy) && entry.modelOverride) {
preserved.providerOverride = entry.providerOverride;
preserved.modelOverride = entry.modelOverride;
preserved.modelOverrideSource = "user";
}
Analyzed PR: #63155 at commit Last updated on: 2026-04-08T16:38:00Z |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 69610faf2f
ℹ️ 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".
| preserved.modelOverrideSource = "user"; | ||
| } | ||
|
|
||
| if (entry.authProfileOverrideSource === "user" && entry.authProfileOverride) { |
There was a problem hiding this comment.
Preserve legacy auth profile overrides on reset
The new reset guard only keeps authProfileOverride when authProfileOverrideSource === "user", but older persisted sessions can have an explicit user profile override without the source field. In that upgrade scenario, /reset//new now drops the auth profile while still keeping the model override, which can silently switch credentials/account selection after reset. Please treat a missing source as legacy-user when authProfileOverride is present (or backfill it before reset), similar to how legacy modelOverrideSource is handled.
Useful? React with 👍 / 👎.
…3155) * fix(gateway): clear auto-fallback model override on session reset When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in cb0a752 ("fix: preserve reset session behavior config") * fix(gateway): preserve explicit reset model selection * fix(gateway): track reset model override source * fix(gateway): preserve legacy reset model overrides * docs(changelog): add session reset merge note --------- Co-authored-by: termtek <[email protected]>
…enclaw#63155) * fix(gateway): clear auto-fallback model override on session reset When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in d38868a ("fix: preserve reset session behavior config") * fix(gateway): preserve explicit reset model selection * fix(gateway): track reset model override source * fix(gateway): preserve legacy reset model overrides * docs(changelog): add session reset merge note --------- Co-authored-by: termtek <[email protected]>
…enclaw#63155) * fix(gateway): clear auto-fallback model override on session reset When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in 2ec7272 ("fix: preserve reset session behavior config") * fix(gateway): preserve explicit reset model selection * fix(gateway): track reset model override source * fix(gateway): preserve legacy reset model overrides * docs(changelog): add session reset merge note --------- Co-authored-by: termtek <[email protected]>
…enclaw#63155) * fix(gateway): clear auto-fallback model override on session reset When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in e848007 ("fix: preserve reset session behavior config") * fix(gateway): preserve explicit reset model selection * fix(gateway): track reset model override source * fix(gateway): preserve legacy reset model overrides * docs(changelog): add session reset merge note --------- Co-authored-by: termtek <[email protected]>
…enclaw#63155) * fix(gateway): clear auto-fallback model override on session reset When `persistFallbackCandidateSelection()` writes a fallback provider override with `authProfileOverrideSource: "auto"`, the override was incorrectly preserved across `/reset` and `/new` commands. This caused sessions to keep using the fallback provider even after the user changed the agent config primary provider, because the session store override takes precedence over the config default. Now the override fields (`providerOverride`, `modelOverride`, `authProfileOverride`, `authProfileOverrideSource`, `authProfileOverrideCompactionCount`) are only carried forward when `authProfileOverrideSource === "user"` (i.e. explicit `/model` command). System-driven overrides are dropped on reset so the session picks up the current config default. Introduced in f0e2431 ("fix: preserve reset session behavior config") * fix(gateway): preserve explicit reset model selection * fix(gateway): track reset model override source * fix(gateway): preserve legacy reset model overrides * docs(changelog): add session reset merge note --------- Co-authored-by: termtek <[email protected]>
Summary
/resetand/newcommandsproviderOverride/modelOverride/authProfileOverrideacross session reset whenauthProfileOverrideSource === "user"(explicit/modelcommand)authProfileOverrideSource: "auto", from fallback rotation) are now dropped on reset so the session picks up the current config defaultChange Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
providerOverride,modelOverride,authProfileOverride,authProfileOverrideSource, andauthProfileOverrideCompactionCountto the fields unconditionally copied during session reset inperformGatewaySessionReset(). This was correct for user-driven/modelselections (authProfileOverrideSource: "user"), but it also preserved fallback-driven overrides (authProfileOverrideSource: "auto") written bypersistFallbackCandidateSelection().persistFallbackCandidateSelection()writesproviderOverridewithauthProfileOverrideSource: "auto", (3) user updates agent config to a different primary provider, (4)/resetor/newcopies the stale fallback override to the new session, (5) new session ignores the config change and keeps using the fallback provider.authProfileOverrideSource === "user"so only explicit user selections survive reset.Regression Test Plan (if applicable)
authProfileOverrideSource: "auto"should not carry forward override fields; session reset withauthProfileOverrideSource: "user"should preserve them.User-visible / Behavior Changes
After a fallback rotation,
/resetor/newnow returns the session to the configured default model/provider instead of keeping the fallback override. Explicit/modelselections continue to be preserved across reset as before.Security Impact (required)
NoNoNoNoNo