Skip to content

[Security][Remote Connector]: Add env var auth config for RESP#2949

Merged
sammshen merged 2 commits intoLMCache:devfrom
sammshen:env-var-resp-auth
Apr 4, 2026
Merged

[Security][Remote Connector]: Add env var auth config for RESP#2949
sammshen merged 2 commits intoLMCache:devfrom
sammshen:env-var-resp-auth

Conversation

@sammshen
Copy link
Copy Markdown
Contributor

@sammshen sammshen commented Apr 3, 2026

Support LMCACHE_RESP_USERNAME, LMCACHE_RESP_PASSWORD, LMCACHE_RESP_HOST, and LMCACHE_RESP_PORT environment variables in both MP and non-MP modes. Env vars are read inside the adapter at creation time so credentials are never stored in the config object or printed in startup logs.

What this PR does / why we need it:

Special notes for your reviewers:

If applicable:

  • this PR contains user facing changes - docs added
  • this PR contains unit tests

Note

Medium Risk
Touches connection/auth configuration for Redis/Valkey in both MP and non-MP code paths; precedence and fallback logic changes could cause misconfiguration or unexpected connection targets if env vars are set incorrectly.

Overview
Adds environment-variable defaults for RESP credentials and endpoint (LMCACHE_RESP_USERNAME, LMCACHE_RESP_PASSWORD, LMCACHE_RESP_HOST, LMCACHE_RESP_PORT) in both MP mode (resp_l2_adapter) and non-MP mode (RESPConnectorAdapter), with config/URL values taking precedence to keep secrets out of logged configs.

Updates RESP documentation and example config to recommend env vars for auth, and adjusts the non-MP sample URL scheme to resp://. Adds unit tests covering precedence (config > env > default) for host/port and credentials.

Reviewed by Cursor Bugbot for commit a044120. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ability to configure Redis/RESP connection details and credentials via environment variables, ensuring sensitive information is kept out of configuration files and logs. Documentation and examples have been updated to promote this practice. Feedback was provided regarding the logic used for environment variable overrides; specifically, using the "or" operator prevents overriding a non-empty configuration value with an empty string. It is recommended to use "os.environ.get(key, default)" to correctly handle cases where an empty string is an intended value.

Comment on lines +150 to +154
host = os.environ.get("LMCACHE_RESP_HOST", "") or config.host
port_str = os.environ.get("LMCACHE_RESP_PORT", "")
port = int(port_str) if port_str else config.port
username = os.environ.get("LMCACHE_RESP_USERNAME", "") or config.username
password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or config.password
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.

medium

The use of the or operator for environment variable overrides prevents setting a value to an empty string if a default exists in the configuration. This is particularly problematic for username and password, where an empty string is a valid value indicating no authentication. Using os.environ.get(key, default) is a more robust pattern for these overrides.

Suggested change
host = os.environ.get("LMCACHE_RESP_HOST", "") or config.host
port_str = os.environ.get("LMCACHE_RESP_PORT", "")
port = int(port_str) if port_str else config.port
username = os.environ.get("LMCACHE_RESP_USERNAME", "") or config.username
password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or config.password
host = os.environ.get("LMCACHE_RESP_HOST", config.host)
port_env = os.environ.get("LMCACHE_RESP_PORT")
port = int(port_env) if port_env else config.port
username = os.environ.get("LMCACHE_RESP_USERNAME", config.username)
password = os.environ.get("LMCACHE_RESP_PASSWORD", config.password)

Comment on lines +49 to +54
username = os.environ.get("LMCACHE_RESP_USERNAME", "") or str(
extra_config.get("username", "")
)
password = os.environ.get("LMCACHE_RESP_PASSWORD", "") or str(
extra_config.get("password", "")
)
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.

medium

Similar to the L2 adapter, using or for environment variable overrides prevents overriding a non-empty configuration value with an empty string (e.g., to disable authentication). It is better to use os.environ.get(key, default) to correctly handle cases where the environment variable is explicitly set to an empty string.

        username = os.environ.get("LMCACHE_RESP_USERNAME", str(extra_config.get("username", "")))
        password = os.environ.get("LMCACHE_RESP_PASSWORD", str(extra_config.get("password", "")))

Comment on lines +59 to +61
host = os.environ.get("LMCACHE_RESP_HOST", "") or parsed_url.host
port_str = os.environ.get("LMCACHE_RESP_PORT", "")
port = int(port_str) if port_str else parsed_url.port
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.

medium

Using os.environ.get(key, default) is cleaner and more consistent for handling environment variable overrides compared to the or pattern, which can have unexpected behavior with empty strings.

Suggested change
host = os.environ.get("LMCACHE_RESP_HOST", "") or parsed_url.host
port_str = os.environ.get("LMCACHE_RESP_PORT", "")
port = int(port_str) if port_str else parsed_url.port
host = os.environ.get("LMCACHE_RESP_HOST", parsed_url.host)
port_env = os.environ.get("LMCACHE_RESP_PORT")
port = int(port_env) if port_env else parsed_url.port

Comment thread lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py Outdated
@sammshen sammshen requested review from deng451e and royyhuang April 3, 2026 22:51
Copy link
Copy Markdown
Contributor

@royyhuang royyhuang left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM!

* - Variable
- Description
* - ``LMCACHE_RESP_USERNAME``
- Redis ACL username. Overrides ``username`` in config/JSON.
Copy link
Copy Markdown
Contributor

@royyhuang royyhuang Apr 3, 2026

Choose a reason for hiding this comment

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

Typically, env var are set for long term usage, like a default value. I would recommend have the command line args override env var instead of the other way around.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agreed

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 22a083a. Configure here.

# which serve as defaults. This keeps secrets out of logged
# config while allowing explicit CLI overrides.
host = config.host or os.environ.get("LMCACHE_RESP_HOST", "")
port = config.port if config.port else int(os.environ.get("LMCACHE_RESP_PORT", "0"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Env var host/port fallback unreachable in MP mode

High Severity

The env var fallback for LMCACHE_RESP_HOST and LMCACHE_RESP_PORT in _create_resp_l2_adapter is dead code. from_dict() validates that host is a non-empty string and port is a positive integer, raising ValueError before the adapter factory ever runs. A user who omits host/port from the JSON and relies solely on env vars will get a crash at config parsing time, not a graceful fallback. The documentation, help() text, and tests all advertise this feature, but it cannot work.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 22a083a. Configure here.

else int(os.environ.get("LMCACHE_RESP_PORT", "0"))
)
username = config.username or os.environ.get("LMCACHE_RESP_USERNAME", "")
password = config.password or os.environ.get("LMCACHE_RESP_PASSWORD", "")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tests duplicate logic instead of exercising production code

Medium Severity

Every test in this file copy-pastes the env var resolution logic inline (e.g. config.host or os.environ.get(...)) instead of calling _create_resp_l2_adapter or RESPConnectorAdapter.create_connector. The tests verify their own inlined logic, not the production code. They will always pass even if the real adapters break — and in fact they mask the from_dict validation bug that makes host/port env var fallback unreachable in MP mode.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by project rule: LMCache Code Review Style Guide

Reviewed by Cursor Bugbot for commit 22a083a. Configure here.

parsed_url.port
if parsed_url.port
else int(os.environ.get("LMCACHE_RESP_PORT", "0"))
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Env var host/port fallback unreachable in non-MP mode

High Severity

The env var fallback for LMCACHE_RESP_HOST and LMCACHE_RESP_PORT at lines 57–62 is dead code in non-MP mode. The parse_remote_url function (called just above on line 54) contains assert host is not None and assert port is not None, which will crash with an AssertionError for any URL missing a host or port — before the fallback logic ever runs. A user who omits host/port from remote_url expecting the env vars to fill them in will get an assertion crash instead.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 22a083a. Configure here.

sammshen added 2 commits April 3, 2026 23:16
Support LMCACHE_RESP_USERNAME, LMCACHE_RESP_PASSWORD, LMCACHE_RESP_HOST,
and LMCACHE_RESP_PORT environment variables in both MP and non-MP modes.
Env vars are read inside the adapter at creation time so credentials are
never stored in the config object or printed in startup logs.

Signed-off-by: Samuel Shen <slshen@tensormesh.ai>
Change precedence so config/CLI args override env vars (env vars serve
as defaults). Add unit tests for the precedence logic in both MP and
non-MP modes.

Signed-off-by: Samuel Shen <slshen@tensormesh.ai>
@sammshen sammshen force-pushed the env-var-resp-auth branch from 22a083a to a044120 Compare April 3, 2026 23:16
@deng451e deng451e added the full Run comprehensive tests on this PR label Apr 3, 2026
@sammshen sammshen enabled auto-merge (squash) April 4, 2026 00:39
@sammshen sammshen merged commit c9d9053 into LMCache:dev Apr 4, 2026
46 of 48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

full Run comprehensive tests on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants