Skip to content

fix(guardrails): expand os.environ/ references in every litellm_params field - #34570

Open
mubashir1osmani wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_guardrail_env_reference_resolution
Open

fix(guardrails): expand os.environ/ references in every litellm_params field#34570
mubashir1osmani wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_guardrail_env_reference_resolution

Conversation

@mubashir1osmani

@mubashir1osmani mubashir1osmani commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • initialize_guardrail only expanded os.environ/ for api_key and api_base, so every other guardrail field kept the literal reference string. A guardrail registered with aws_region_name="os.environ/AWS_REGION" handed boto3 the string "os.environ/AWS_REGION" and failed the request
  • The same silently broke aws_access_key_id, aws_secret_access_key, the presidio analyzer/anonymizer bases, and the rest of the credential fields, none of which are reachable through api_key/api_base

How it solves it:

  • Resolves every string field that starts with os.environ/ instead of two named ones
  • A reference that resolves to nothing now becomes None rather than the string "None", so the downstream client falls back to its own credential chain (pod identity, for example) instead of authenticating with a literal "None"

Relevant issues

Linear ticket

Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review

Screenshots / Proof of Fix

Reproduced against the live stage proxy before the fix. Registering a bedrock guardrail with the three os.environ/ AWS params and sending a chat request returned:

500 {"error":{"message":"Bedrock guardrail failed: Invalid AWS region format: 'os.environ/AWS_REGION'.
Region names must contain only lowercase letters, digits, and hyphens."}}

The same guardrail registered without those params blocked correctly with 400 "Violated guardrail policy", confirming the literal string was the only difference.

LitellmParams has 20+ str | None fields that were all affected, including aws_region_name, aws_access_key_id, aws_secret_access_key, aws_session_token, aws_role_name, presidio_analyzer_api_base, presidio_anonymizer_api_base, auth_token, and credentials.

Type

🐛 Bug Fix

Changes

Adds _resolve_env_references() and calls it in place of the two hardcoded field checks. The helper builds the resolved values with a comprehension and returns model_copy(update=...), so nothing is mutated in place.

QA runbook

The new test is a real regression test, not coverage padding. Reverting the helper to the old two-field behavior makes it fail on the exact symptom:

$ pytest tests/test_litellm/proxy/guardrails/test_guardrail_registry.py::test_resolve_env_references_expands_every_string_field
E  AssertionError: assert 'os.environ/T...RDRAIL_REGION' == 'us-east-1'
1 failed

# with the fix in place
1 passed

# whole file, no regressions
18 passed

It also pins the None-not-"None" behavior for an unset reference, and asserts literal values and unrelated fields survive the copy.

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

…s field

initialize_guardrail only expanded os.environ/ for api_key and api_base, so
every other field kept the literal reference string. A guardrail registered
with aws_region_name="os.environ/AWS_REGION" handed boto3 the string
"os.environ/AWS_REGION", which failed the request with "Invalid AWS region
format: 'os.environ/AWS_REGION'. Region names must contain only lowercase
letters, digits, and hyphens." The same silently broke aws_access_key_id,
aws_secret_access_key, the presidio analyzer/anonymizer bases, and the rest of
the credential fields, none of which are reachable through api_key/api_base.

Resolve every string field that starts with os.environ/ instead of two named
ones. A reference that resolves to nothing now becomes None rather than the
string "None", so the downstream client falls back to its own credential chain
(pod identity, for example) instead of authenticating with a literal "None".

Reproduced against the live stage proxy before the fix: registering a bedrock
guardrail with the three os.environ/ AWS params returned 500 with the invalid
region message, while the same guardrail without them blocked correctly.
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR generalizes environment-reference resolution for guardrail parameters.

  • Adds a helper that resolves top-level string fields beginning with os.environ/.
  • Replaces the dedicated api_key and api_base handling with that helper.
  • Adds regression coverage for string-valued Bedrock, Presidio, and credential parameters.

Confidence Score: 3/5

This PR should not merge until environment references are resolved before typed guardrail parameters are validated.

Numeric guardrail fields still receive the literal os.environ/... string during LitellmParams construction and fail validation before the new resolver can read the environment value.

Files Needing Attention: litellm/proxy/guardrails/guardrail_registry.py, tests/test_litellm/proxy/guardrails/test_guardrail_registry.py

Important Files Changed

Filename Overview
litellm/proxy/guardrails/guardrail_registry.py Generalizes secret resolution, but performs it after model validation, leaving typed numeric parameters unable to use environment references.
tests/test_litellm/proxy/guardrails/test_guardrail_registry.py Covers optional and literal string fields but does not exercise environment references for typed fields such as timeout or Bedrock thresholds.

Reviews (1): Last reviewed commit: "fix(guardrails): expand os.environ/ refe..." | Re-trigger Greptile

Comment on lines +398 to +400
for name, value in litellm_params.model_dump().items()
if isinstance(value, str) and value.startswith("os.environ/")
}

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.

P1 Typed environment references fail

When a guardrail uses an environment reference for a typed parameter such as timeout or content_filter_threshold, LitellmParams validates the literal os.environ/... string before this resolver runs, causing guardrail initialization to fail even when the environment value is valid.

Knowledge Base Used: Guardrails

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_guardrail_env_reference_resolution (de74191) with litellm_internal_staging (7263aa0)1

Open in CodSpeed

Footnotes

  1. No successful run was found on litellm_internal_staging (57ed2ed) during the generation of this report, so 7263aa0 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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.

1 participant