mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-15 04:19:08 +00:00
fix(proxy): never log billing credential values when they fail to resolve
Accepting inline PEM turned the cert env vars into secret-bearing values, but the disable warning still echoed them. A value that is neither a readable path nor `-----BEGIN`-prefixed PEM, for example a key with a preamble or a malformed secret, fell through to the path branch and was written to the proxy logs verbatim, exposing the client certificate or private key to anyone who can read them. The warning now names the offending environment variables and tells the operator what a valid value looks like, without ever printing one
This commit is contained in:
parent
37c6bad289
commit
269ee7e876
2 changed files with 40 additions and 5 deletions
|
|
@ -229,14 +229,24 @@ def load_billing_metrics_config(
|
|||
)
|
||||
return None
|
||||
|
||||
required_paths = [paths.client_cert_path, paths.client_key_path] + (
|
||||
[paths.ca_cert_path] if paths.ca_cert_path else []
|
||||
)
|
||||
unreadable = [path for path in required_paths if not os.path.isfile(path)]
|
||||
# Report the variable names, never their values. A value that is neither a
|
||||
# readable path nor recognizable PEM is still secret material, and this
|
||||
# warning would otherwise copy a client key straight into the proxy logs.
|
||||
unreadable = [
|
||||
env_name
|
||||
for env_name, path in (
|
||||
(CLIENT_CERT_ENV, paths.client_cert_path),
|
||||
(CLIENT_KEY_ENV, paths.client_key_path),
|
||||
(CA_CERT_ENV, paths.ca_cert_path),
|
||||
)
|
||||
if path and not os.path.isfile(path)
|
||||
]
|
||||
if unreadable:
|
||||
verbose_proxy_logger.warning(
|
||||
"Enterprise billing metrics disabled: certificate file(s) not found: %s",
|
||||
"Enterprise billing metrics disabled: %s did not resolve to a readable certificate file. "
|
||||
"Set each to a file path, or to inline PEM content beginning with '%s'.",
|
||||
", ".join(unreadable),
|
||||
_PEM_PREFIX,
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -240,6 +240,31 @@ def test_load_config_with_inline_pem_disabled_when_unwritable(monkeypatch):
|
|||
assert bm.load_billing_metrics_config(license_data=None, litellm_version="1.0") is None
|
||||
|
||||
|
||||
def test_load_config_never_logs_credential_values(monkeypatch):
|
||||
"""
|
||||
A value that is neither a readable path nor `-----BEGIN`-prefixed PEM is
|
||||
still secret material. The disable warning must name the env vars, never
|
||||
echo their contents, or a malformed key lands in the proxy logs.
|
||||
"""
|
||||
secret_material = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQ-not-pem-prefixed"
|
||||
monkeypatch.setenv(bm.ENDPOINT_ENV, "https://collector.example:4317")
|
||||
monkeypatch.setenv(bm.CLIENT_CERT_ENV, secret_material)
|
||||
monkeypatch.setenv(bm.CLIENT_KEY_ENV, secret_material)
|
||||
|
||||
logged: List[str] = []
|
||||
|
||||
def _capture(msg, *args):
|
||||
logged.append(msg % args if args else msg)
|
||||
|
||||
monkeypatch.setattr(bm.verbose_proxy_logger, "warning", _capture)
|
||||
|
||||
assert bm.load_billing_metrics_config(license_data=None, litellm_version="1.0") is None
|
||||
|
||||
joined = "\n".join(logged)
|
||||
assert secret_material not in joined
|
||||
assert bm.CLIENT_CERT_ENV in joined and bm.CLIENT_KEY_ENV in joined
|
||||
|
||||
|
||||
def test_load_config_with_empty_pem_env_is_disabled(monkeypatch):
|
||||
"""Empty stays empty: an unset secret must not be mistaken for inline PEM."""
|
||||
monkeypatch.setenv(bm.ENDPOINT_ENV, "https://collector.example:4317")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue