Skip to content

fix: prevent invalid proxy tokens after managed profile changes - #209

Open
saurya wants to merge 2 commits into
mainfrom
fix/preserve-managed-key-on-profile-change
Open

fix: prevent invalid proxy tokens after managed profile changes#209
saurya wants to merge 2 commits into
mainfrom
fix/preserve-managed-key-on-profile-change

Conversation

@saurya

@saurya saurya commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • omit blank and stale BYOK values from OpenHands-managed frontend payloads
  • verify and reuse an existing member-managed LiteLLM key when a managed profile save omits its key
  • rotate only when that stored key is absent or fails verification
  • prevent raw managed API keys from being persisted in personal or organization LLM profiles

Root cause

Switching an active conversation from Kimi K3 to an OpenHands-managed Gemini profile sent api_key: \"\". The backend interpreted that blank value as a key deletion/regeneration request, while active-profile synchronization could retain a raw key that no longer matched the current managed credential.

Verification

  • PYTHONPATH=\"$PWD/enterprise:$PWD\" poetry -C enterprise run pytest -q tests/unit/test_saas_settings_store.py tests/unit/test_org_profiles.py — 67 passed
  • cd frontend && npm run test -- --run __tests__/routes/llm-settings.test.tsx — 81 passed
  • root and enterprise Python pre-commit configurations — passed
  • targeted ESLint and Prettier checks — passed
  • cd frontend && npm run build — passed

The new regressions were confirmed failing before the fix for blank managed-key reuse, raw managed-profile persistence, and stale BYOK leakage into the managed Gemini payload.

Why key regeneration is preserved

The fix changes an empty managed-provider payload from an unconditional rotation signal into a request to reuse the member's stored managed key when that key is still valid. Regeneration continues in both required cases:

  1. No managed key exists: the fallback is absent, so _ensure_api_key() follows its existing missing-key path, deletes any key under the deterministic alias, and generates a replacement.
  2. The stored managed key is invalid: LiteLlmManager.verify_existing_key() returns false, so the existing invalid-key path deletes the alias and generates a replacement.

Existing transition behavior is also preserved:

  • A member switching from a custom BYOK configuration has has_custom_llm_api_key=true, so the custom key is never selected as the managed fallback and the managed-key generation path still runs.
  • An explicit key in the request continues to take precedence over the fallback and is verified using the existing flow.
  • Organization-managed keys are excluded from the member fallback path and continue to resolve through the organization key lifecycle.

Regression coverage asserts valid stored-key reuse without rotation, invalid fallback rotation, custom-key-to-managed generation, and unchanged explicit managed-key behavior.

Related

This pull request was created by an AI agent (OpenHands) on behalf of Saurya Velagapudi.


Enterprise server image for this PR:

ghcr.io/openhands/enterprise-server:sha-fb89b42

Co-authored-by: openhands <openhands@all-hands.dev>
@saurya saurya changed the title Fix invalid proxy tokens after managed profile changes fix: prevent invalid proxy tokens after managed profile changes Aug 19, 2026
@github-actions github-actions Bot added the type: fix A bug fix label Aug 19, 2026
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  enterprise/server/routes
  org_profiles.py 258-265
  enterprise/storage
  saas_settings_store.py 178-179, 183-185, 189, 666-684, 880, 894-895, 930-933
Project Total  

This report was generated by python-coverage-comment-action

@saurya
saurya marked this pull request as ready for review August 19, 2026 22:35
@saurya
saurya requested a review from dylan-openhands August 19, 2026 22:35
@linear

linear Bot commented Aug 25, 2026

Copy link
Copy Markdown
OHE-3109 [Bug] Switching an active conversation to Gemini ProPreview causes invalid proxy token error

Environment

staging.all-hands.dev

Steps to reproduce

  1. Start a conversation with Kimi K3 selected.
  2. Open Model settings from that conversation.
  3. Change the default profile from Advanced to the basic profile setup.
  4. Choose OpenHands as provider and Gemini ProPreview as model.
  5. Return to the existing conversation.

Actual result

The conversation fails with a 401: invalid proxy server token; the token is missing from the LiteLLM cache or LiteLLM_VerificationTokenTable.

Expected result

The conversation continues with the newly selected profile without an authentication failure.

Context

Related to OHE-2678, but this is a distinct reproduction after changing an active conversation profile. OHE-2678 is Done, so this is tracked separately as a regression.

This issue was created by an AI agent (OpenHands) on behalf of Saurya.

@saurya
saurya requested a review from tofarr August 25, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix A bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant