Skip to content

fix(proxy): preserve master_key set by initialize() during lifespan startup - #22483

Closed
giulio-leone wants to merge 4 commits into
BerriAI:mainfrom
giulio-leone:fix/issue-22330-mcp-auth-context
Closed

fix(proxy): preserve master_key set by initialize() during lifespan startup#22483
giulio-leone wants to merge 4 commits into
BerriAI:mainfrom
giulio-leone:fix/issue-22330-mcp-auth-context

Conversation

@giulio-leone

Copy link
Copy Markdown
Contributor

Summary

Fixes a bug where proxy_startup_event() unconditionally overwrote the global master_key with the result of get_secret_str("LITELLM_MASTER_KEY"), which returns None when the env var is not set. This caused the master_key previously set by initialize() to be lost.

Changes

  • Only overwrite master_key if the env var lookup returns a non-None value

Supersedes #22396 (rebased on main)

@vercel

vercel Bot commented Mar 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Mar 6, 2026 4:27pm

Request Review

@greptile-apps

greptile-apps Bot commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a one-line bug in proxy_startup_event where master_key was unconditionally overwritten with the result of get_secret_str("LITELLM_MASTER_KEY"), which returns None when the env var is unset. The fix wraps the assignment in an if _env_master_key is not None: guard so that a key previously configured by initialize() (e.g. from a config file or programmatic startup) is preserved when the env var is absent.

  • litellm/proxy/proxy_server.py: Assignment guarded with is not None — env var still takes precedence when set, but the config-provided value is no longer silently discarded.
  • tests/test_litellm/proxy/test_preserve_master_key.py: New regression test correctly enters the @asynccontextmanager via async with, patches all external dependencies to avoid network calls, and asserts the key is preserved. The finally block restores master_key but does not restore premium_user (already raised in a prior thread).

Confidence Score: 5/5

  • This PR is safe to merge — the fix is minimal, semantically correct, and cannot break existing behaviour.
  • The change is a single conditional guard (if _env_master_key is not None) around an existing assignment. When the env var IS set the behaviour is identical to before; when it is absent the config-provided key is now correctly preserved. The regression test, while having a minor state-cleanup gap for premium_user (noted in a prior review thread), still exercises the exact code path under test and would catch a regression of the fix.
  • No files require special attention.

Important Files Changed

Filename Overview
tests/test_litellm/proxy/test_preserve_master_key.py New regression test correctly uses async with to enter the @asynccontextmanager and patches all external dependencies; premium_user module-level state is not restored in the finally block, which may pollute subsequent tests.
litellm/proxy/proxy_server.py Minimal, correct fix: the master_key env-var assignment is now guarded by if _env_master_key is not None, preserving any value previously set by initialize() when the env var is absent.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[proxy_startup_event starts] --> B[init_verbose_loggers]
    B --> C{premium_user is False?}
    C -- Yes --> D[premium_user = license_check.is_premium]
    C -- No --> E[Read LITELLM_MASTER_KEY env var]
    D --> E
    E --> F{env var result is not None?}
    F -- Yes --> G[master_key = env var value\nenv var takes precedence]
    F -- No --> H[master_key unchanged\nconfig-provided value preserved]
    G --> I[Load config and DB setup]
    H --> I
Loading

Last reviewed commit: cd6241c

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a bug where proxy_startup_event() unconditionally overwrote the global master_key with the result of get_secret_str("LITELLM_MASTER_KEY"), which could return None when the env var is not set — discarding any value previously set by initialize().

Changes:

  • Guard the master_key assignment so it only overwrites the existing value when LITELLM_MASTER_KEY env var is actually set

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread litellm/proxy/proxy_server.py Outdated
@giulio-leone

Copy link
Copy Markdown
Contributor Author

Thanks for the summary — accurate assessment.

@CLAassistant

CLAassistant commented Mar 4, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@giulio-leone

Copy link
Copy Markdown
Contributor Author

Quick intervention note to unblock this PR efficiently:

I’m seeing a repeated failure pattern across the latest LiteLLM PRs:

  • analyze jobs failing (actions, javascript-typescript, python, ruby)
  • lint failing
  • core test shards failing (root, other-3, proxy-guardrails, proxy-unit-a1)
  • Vercel deployment failed
  • license/cla pending on several PRs

Recommended resolution order (lowest risk):

  1. Ensure CLA is signed for the PR author.
  2. Rebase on latest main to absorb CI/workflow drift.
  3. Run lint + targeted failing shards first, then full matrix.
  4. Re-run checks and only then request review.

If helpful, I can post a per-PR checklist with the first failing job links and a minimal fix order.

Comment thread litellm/proxy/proxy_server.py
Comment thread tests/test_litellm/proxy/test_preserve_master_key.py
@giulio-leone

Copy link
Copy Markdown
Contributor Author

All review feedback has been addressed in the latest push. The PR is ready for re-review and merge. Thank you! 🙏

giulio-leone and others added 2 commits March 5, 2026 21:28
Verifies that a master_key set by initialize() from config is not
overwritten when LITELLM_MASTER_KEY env var is absent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread litellm/proxy/proxy_server.py Outdated
Comment on lines +780 to +781
if _env_master_key:
master_key = _env_master_key

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use is not None for explicit env-var-presence check

The truthiness guard if _env_master_key: treats an empty string the same as None. If LITELLM_MASTER_KEY is explicitly set to an empty string in the environment, the current check would silently ignore it and preserve the config-provided value. For a security credential, an explicit is not None check is more semantically precise — it only falls back to the config value when the env var is genuinely absent (returns None), not when it is falsy.

Consider changing the guard to:

if _env_master_key is not None:

- Test used 'await' on @asynccontextmanager which never enters the body;
  changed to 'async with' so the startup code actually executes.
- Changed truthiness check to 'is not None' for master_key guard to
  correctly handle empty-string edge case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread tests/test_litellm/proxy/test_preserve_master_key.py
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@giulio-leone

Copy link
Copy Markdown
Contributor Author

Closing to reduce PR volume. The fix remains valid — happy to resubmit individually if the team finds it useful.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants