Repository navigation
feat(fips): build grpcio from source against system OpenSSL and drop its scanner waiver - #42912
devin-ai-integration[bot] wants to merge 8 commits into
Conversation
Dockerfile.fips builds on chainguard-base-fips with FIPS-provider-linked python/node/openssl from the org apk repo (CMVP #5132). A fips-check stage runs openssl-fips-test and an ELF allowlist gate: every native binary must be in the reviewed fips_elf_inventory.txt or carry an explicit bundled-crypto waiver, so new native deps fail the build until reviewed. Known offenders are waived pending the dependency-fix workstream and the report ships at /fips-scan-report.txt
…tellm_fips_c4_grpcio_system_openssl
…its scanner waiver Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
bugbot run |
… job holds) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| */hf_xet/hf_xet.abi3.so) ;; | ||
| */_awscrt.abi3.so) ;; | ||
| */pyroscope/_native__lib*.so) ;; | ||
| */psycopg_binary.libs/libcrypto-*) ;; |
There was a problem hiding this comment.
psycopg libcrypto waiver never matches
High Severity
is_waived matches psycopg_binary.libs/libcrypto-* (hyphen), but the inventoried files are libcrypto.so.3 and libcrypto.so.1.1.1k. Those copies carry OpenSSL version strings and do not NEEDED libcrypto.so.3, so the gate reports VIOLATION and fails fips-check.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit e707821. Configure here.
There was a problem hiding this comment.
The scanned path keeps the auditwheel hash (libcrypto-2a5143d4.so.3), so the hyphen pattern matches. Only the inventory line is normalized to libcrypto.so.3
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…tack Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
| bodies: Final = tuple(JSON_OBJECT.validate_json(response.content) for response in responses) | ||
| for response, body in zip(responses, bodies): | ||
| assert response.status_code == 200, response.text | ||
| assert isinstance(body["id"], str) and body["id"].startswith("chatcmpl-"), response.text |
There was a problem hiding this comment.
No retry after worker SIGKILL
Medium Severity
After SIGKILL, the test immediately calls scenario.model() and five chat completions on the reused owned.gateway client. Gateway.request does not catch transport errors, and Gateway.post asserts 200 on the first try. A reset keep-alive to the victim or a briefly unready respawn fails the test instead of waiting for the survivor to accept again.
Reviewed by Cursor Bugbot for commit c7cf432. Configure here.
There was a problem hiding this comment.
Fixed in fa694bd: a fresh httpx client probes the survivor inside eventually before the burst
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
1 issue from previous review remains unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit fa694bd. Configure here.


TLDR
Problem this solves:
How it solves it:
Dockerfile.fipsbuilds grpcio from source withGRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1, socygrpclinks the systemlibcrypto.so.3uv.lock, so it is cached until grpcio moveslibcrypto.so.3and carries no BoringSSL string, then strips it (546 MB to 14 MB)scan_bundled_crypto.shno longer waivescygrpc*.so, so a BoringSSL grpcio fails the gate againdocker/Dockerfile.fipsis allowlisted in.github/ci-coverage-allowlist.ymlbecause no pull request job holds the Chainguard apk token the image needsUser Flow
Before: a FIPS operator builds the image and gets a green crypto gate while grpcio still carries its own BoringSSL
docker build -f docker/Dockerfile.fips .and the fips-check stage printsPASS: all N ELF binaries accounted forobjdump -p /app/.venv/lib/python3.13/site-packages/grpc/_cython/cygrpc*.soshows nolibcrypto.so.3,grep -a BoringSSLmatchesAfter: the same build compiles grpcio against the FIPS OpenSSL and the gate would fail if it ever regressed
docker build -f docker/Dockerfile.fips .; the grpcio stage compiles the wheel once (about 6 minutes on 8 cores) and is cached afterwardsgrpc._cython.cygrpc,objdump -plistsNEEDED libcrypto.so.3, and the gate printsPASSVIOLATION .../cygrpc.cpython-313-ARCH-linux-gnu.so [BoringSSL]Linear ticket
Resolves LIT-8435
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Setup: the Chainguard FIPS base needs a registry token this run does not have, so the grpcio build stage was replayed byte for byte on
python:3.13-slim(build-essential libssl-dev zlib1g-dev binutils, uv 0.11.7), and the scanner was run on the result. Integration rig: real proxy with two workers, Postgres, Redis and the scripted upstream fromtests/integration/_support/upstream.py, no real providerBefore (merge-base 09ebb28 with the pre-fix scanner from 41802 tip e43e984)
Scanner gate on the PyPI grpcio wheel
uv run --no-sync python -m pytest tests/integration/configuration/test_fips_bundled_crypto_scan.py tests/integration/configuration/test_proxy_without_grpc_stack.py -p no:pytest-retry -p no:rerunfailures --hypothesis-seed=8435 --integration-order-seed=8435, run id 2026-09-24T09:13:56Ztest_bundled_boringssl_grpcio_fails_the_fips_gateFAILED:WAIVED .../grpc/_cython/cygrpc.cpython-313-x86_64-linux-gnu.so [BoringSSL],PASS: all 1 ELF binaries accounted for, exit 0 instead of 1; the other 7 nodes passedgrpcio build against system OpenSSL
objdump -p .venv/lib/python3.12/site-packages/grpc/_cython/cygrpc*.so | grep NEEDEDon the PyPI wheel: nolibssl.so.3orlibcrypto.so.3grep -ac BoringSSLon that file: 1After (fa694bd)
Audit matrix, two runs with identical seeds, identical order, 0 skipped, 0 retries
Run ids 2026-09-24T09:23:31Z (8 passed, 62.71s) and 2026-09-24T09:24:35Z (8 passed, 62.92s). Nodes under
tests/integration/configuration/:test_fips_bundled_crypto_scan.py::test_bundled_boringssl_grpcio_fails_the_fips_gate::test_system_openssl_linked_grpcio_at_its_inventory_path_is_clean::test_unreviewed_elf_outside_the_inventory_fails_the_gate::test_empty_tree_passestest_proxy_without_grpc_stack.py::test_chat_completions_serves_without_the_grpc_stack::test_streaming_chat_completion_serves_without_the_grpc_stack::test_messages_and_responses_serve_without_the_grpc_stack::test_surviving_worker_keeps_serving_without_the_grpc_stackScanner gate on the PyPI grpcio wheel
VIOLATION .../cygrpc.cpython-313-x86_64-linux-gnu.so [BoringSSL]and exits 1 for the PyPI wheel,CLEANfor alibcrypto.so.3linked ELF at the inventory path,VIOLATION [unreviewed]outside itgrpcio build against system OpenSSL
docker buildof the replayed grpcio stage:GRPCIO_VERSION 1.78.0read fromuv.lock, wheel compiled in 6m07s wall on 8 cores,pip wheelchain exit 0objdump -pon the installed, strippedcygrpc:NEEDED libssl.so.3,NEEDED libcrypto.so.3,NEEDED libz.so.1,libstdc++.so.6,libm.so.6,libc.so.6;grep -a BoringSSLmatches nothing; size 14,422,672 bytespython -c "import grpc._cython.cygrpc; import grpc; grpc.secure_channel('127.0.0.1:1', grpc.ssl_channel_credentials()).close(); print(grpc.__version__)"prints1.78.0docker/scan_bundled_crypto.shon that tree with the repo inventory:CLEAN .../cygrpc.cpython-313-x86_64-linux-gnu.so,PASS: all 1 ELF binaries accounted forProxy without grpcio, polars, google.cloud
sitecustomizethat makesgrpc,polars,google.cloudandgoogle.api_coreunimportable (python -c "import grpc"fails under it)chatcmpl-id, upstream received exactly one request with the sent body; streaming: last SSE chunk id equals the upstream'sresp_id and the upstream text; POST /v1/messages: 200 with one text block carrying the upstream textModuleNotFoundErrorfor grpc or polarsLive A/B of the two wheels against real Google endpoints
The diff moves no Python under
litellm/, so the live leg compares the PyPI grpcio 1.78.0 (bundled BoringSSL) against the source-built grpcio 1.78.0 (NEEDED libcrypto.so.3) in the same process shapegrpc.secure_channeltoaiplatform.googleapis.com:443andgenerativelanguage.googleapis.com:443withgrpc.ssl_channel_credentials(),channel_ready_future(...).result(timeout=15): READY on both wheelslitellm.completion(model="vertex_ai/gemini-2.5-flash", ...)with a real service account: 200 on both wheels, idsO--0au-wJfe00ekP4b7xwAM(PyPI) andV--0au2...(source built)google.cloud.aiplatformModelServiceClient.list_modelsoverModelServiceGrpcTransport: RPC succeeded on both wheels, so cygrpc TLS was on the wire through the system OpenSSLMutation check on the tests: re-adding the waiver, downgrading the VIOLATION line to WAIVED, deleting the cygrpc inventory line, adding
import polarsorimport grpcat the top ofproxy_server.py, and killing the master instead of a worker each turned the matching tests red. Waiving every path did not kill the unreviewed ELF test because that scanner branch never consultsis_waived, so the kill rate is 6 of 7, not above 90 percentType
Infrastructure
Caveats (if any)
Medium
docker/FIPS files come fromlitellm_fips_base_image, so this diff shows them until that PR landspython:3.13-slimwith the identical commandsuv.lockmoves grpcioLow
integration-management(job 2211080, the shard that runs the two new files) and the database, replica, sdk, providers, cost and browser shards are green. Three shards are red with failures that are red on main at the same time:integration-mcp2211079 (test_malformed_bodies_missing_users_and_foreign_servers_are_rejected, main 2210684),integration-extensions2211088 (test_redis_outage_keeps_serving_in_memory_hitsandtest_passthrough_worker_sigkill_leaves_sibling_serving_and_logging, main 2210686 and 2210285),integration-accounting2211081 and one rerun 2211256 (two different tests, each also failing on main in 2210281, 2210055, 2209497).local_testing_part1andusing_litellm_on_windowsfail on main the same way (2210327, 2210297). This diff moves no Python underlitellm/uv venv --seedpulls pip for the sdist build; uv itself is pinned, pip is not--no-install-package polarsis safe when A decides to use itFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/2a0cd462da5846baa5db8b7c178f99d6
Open in Devin Desktop: https://app.devin.ai/desktop/session/2a0cd462da5846baa5db8b7c178f99d6?variant=devin
Requested by: @yucheng-berri