From 23ebd158bf15861b102afd86e0edb090b54e450e Mon Sep 17 00:00:00 2001 From: yucheng Date: Tue, 27 Oct 2026 16:33:22 -0700 Subject: [PATCH] fix(proxy): refuse FIPS mode when cryptography's FIPS provider cannot hash The stock cryptography wheel reads the host's FIPS config and reports FIPS on, but its bundled OpenSSL cannot load the host's FIPS provider, so every operation fails. Require a working SHA-256 alongside the FIPS flag. --- litellm/proxy/common_utils/fips.py | 20 ++++++++++++++------ tests/unit/proxy/common_utils/test_fips.py | 19 +++++++++++++++---- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/litellm/proxy/common_utils/fips.py b/litellm/proxy/common_utils/fips.py index f57f56d3248..671c023bbdb 100644 --- a/litellm/proxy/common_utils/fips.py +++ b/litellm/proxy/common_utils/fips.py @@ -31,13 +31,20 @@ def openssl_enforces_fips() -> bool: def cryptography_enforces_fips() -> bool: - """The cryptography library's own OpenSSL runs with FIPS-only defaults.""" + """The cryptography library's own OpenSSL runs with FIPS-only defaults and its FIPS provider can hash SHA-256.""" try: + from cryptography.exceptions import InternalError, UnsupportedAlgorithm from cryptography.hazmat.bindings._rust import openssl as rust_openssl - - return rust_openssl.is_fips_enabled() - except (ImportError, AttributeError): + from cryptography.hazmat.primitives import hashes + except ImportError: return False + try: + if not rust_openssl.is_fips_enabled(): + return False + hashes.Hash(hashes.SHA256()).finalize() + except (AttributeError, InternalError, UnsupportedAlgorithm): + return False + return True def enforce_fips_mode() -> None: @@ -63,6 +70,7 @@ def enforce_fips_mode() -> None: ) if not cryptography_enforces_fips(): raise FipsModeError( - f"{FIPS_MODE_ENV_VAR} is on but the cryptography library's OpenSSL does not enforce FIPS. Build it against " - f"the system OpenSSL (pip install --no-binary cryptography cryptography), or unset {FIPS_MODE_ENV_VAR}." + f"{FIPS_MODE_ENV_VAR} is on but the cryptography library's OpenSSL has no working FIPS provider. Build it " + "against the system OpenSSL (pip install --no-binary cryptography cryptography), or unset " + f"{FIPS_MODE_ENV_VAR}." ) diff --git a/tests/unit/proxy/common_utils/test_fips.py b/tests/unit/proxy/common_utils/test_fips.py index 98e95263dcb..bd6834af536 100644 --- a/tests/unit/proxy/common_utils/test_fips.py +++ b/tests/unit/proxy/common_utils/test_fips.py @@ -1,8 +1,11 @@ import _hashlib from contextlib import nullcontext +from unittest.mock import Mock import pytest +from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._rust import openssl as rust_openssl +from cryptography.hazmat.primitives import hashes import litellm from litellm.proxy.common_utils.fips import ( @@ -50,10 +53,18 @@ def test_openssl_without_get_fips_mode_does_not_enforce_fips(monkeypatch): assert openssl_enforces_fips() is False -@pytest.mark.parametrize("fips_enabled", [True, False]) -def test_cryptography_enforces_fips_reads_its_openssl_fips_flag(monkeypatch, fips_enabled): +@pytest.mark.parametrize( + "fips_enabled, sha256_broken, enforces", + [(True, False, True), (False, False, False), (True, True, False)], + ids=["fips", "fips-flag-off", "sha256-broken"], +) +def test_cryptography_enforces_fips_needs_the_fips_flag_and_a_working_sha256( + monkeypatch, fips_enabled, sha256_broken, enforces +): monkeypatch.setattr(rust_openssl, "is_fips_enabled", lambda: fips_enabled) - assert cryptography_enforces_fips() is fips_enabled + if sha256_broken: + monkeypatch.setattr(hashes, "Hash", Mock(side_effect=InternalError("Unknown OpenSSL error", []))) + assert cryptography_enforces_fips() is enforces def test_cryptography_without_is_fips_enabled_does_not_enforce_fips(monkeypatch): @@ -78,7 +89,7 @@ def test_this_runners_openssl_does_not_enforce_fips(): ("true", "false", True, True, True, "TLS certificate verification is disabled"), ("true", None, False, True, True, "TLS certificate verification is disabled"), ("true", None, True, False, True, "is on but OpenSSL does not enforce FIPS"), - ("true", None, True, True, False, "cryptography library's OpenSSL does not enforce FIPS"), + ("true", None, True, True, False, "cryptography library's OpenSSL has no working FIPS provider"), ("enforced", None, True, True, True, "LITELLM_FIPS_MODE='enforced' is not a boolean"), ], ids=[