Files
Triple-C/gateway-container/Dockerfile
T
shadowdaoandClaude Opus 5.5 b0cea1240a fix(gateway): bump LiteLLM v1.96.0 -> v1.106.6 for SSRF and admin-escalation CVEs
v1.96.0 is affected by two advisories published since it was pinned:

- CVE-2026-84377 / GHSA-3cv6-jpf6-8222: authenticated SSRF and
  provider-credential exfiltration via unvalidated request-body URLs
  (fixed 1.96.2 on that line). This container holds a billed provider key.
- CVE-2026-114612 / GHSA-7hp6-4w63-5g45: privilege escalation to proxy
  admin via cross-domain reuse of the salt key (fixed 1.103.1; no 1.96.x
  backport).

v1.106.6 (2026-10-28) is the newest stable release with no OSV advisories.
Tag and digest updated together; the index digest was read with
`docker buildx imagetools inspect` and cosign-verified against LiteLLM's
pinned public key. GATEWAY_REGISTRY_IMAGE in gateway.rs is kept in
lockstep.

Smoke-tested with a config shaped like render_config()'s output: the
proxy starts, /v1/messages without a key is a 401, and with the master
key the Anthropic-format request is translated and routed to the
configured OpenAI base. Note this LiteLLM refuses to start with no
master_key at all; Triple-C always renders one, so that is not a
regression for us.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:01:37 -08:00

64 lines
4.0 KiB
Docker

# Triple-C model gateway — a LiteLLM proxy that speaks the Anthropic Messages
# API on the front and OpenAI (or any other LiteLLM provider) on the back.
#
# Claude Code only ever talks the Anthropic Messages API: it POSTs to
# `${ANTHROPIC_BASE_URL}/v1/messages`. OpenAI has no such route, so an OpenAI
# key cannot be pointed at Claude Code directly. LiteLLM's proxy exposes
# `/v1/messages` in Anthropic format and translates each request to the
# configured provider, which is what makes first-class OpenAI support possible.
#
# ── Why this image is built FROM the official LiteLLM image ──────────────────
# We deliberately do NOT `pip install litellm` ourselves. The official image is
# built by the LiteLLM maintainers from a locked dependency set and already
# carries the proxy entrypoint (`docker/prod_entrypoint.sh`), the admin UI and
# the Prisma bits. Hand-rolling a pip install would mean re-resolving the whole
# dependency tree on every build — exactly the surface that got poisoned in the
# incident below — and would drift from what upstream tests.
#
# ── Why the version is PINNED and why THIS version ───────────────────────────
# LiteLLM 1.82.7 and 1.82.8 were published to PyPI containing malware. Anything
# that resolves `litellm` at build time (or floats a `latest`/`main-latest` tag)
# can silently land on a compromised build, so the tag here is pinned to an
# exact release and additionally pinned by digest — a tag can be re-pushed, a
# digest cannot.
#
# The malicious wheels never became images — the official images build from a
# pinned requirements.txt and were confirmed unaffected (GHSA-5mg7-485q-xm76,
# https://docs.litellm.ai/blog/security-update-march-2026). The reason to pin is
# to keep it that way: a floating tag re-resolves, and this container ends up
# holding an OpenAI API key.
#
# v1.106.6 is chosen rather than the nearest clean post-incident release (1.83.0)
# because the intervening releases fix a run of *ordinary* proxy CVEs that matter
# for a gateway published on a host port: SQL injection in API-key verification
# (CVE-2026-42208, fixed 1.83.7), auth bypass via Host header injection
# (CVE-2026-49468, fixed 1.84.0), MCP auth bypass (CVE-2026-59822, fixed
# 1.84.0), authenticated SSRF and provider-credential exfiltration via
# unvalidated request-body URLs (CVE-2026-84377 / GHSA-3cv6-jpf6-8222, fixed
# 1.96.2 on the line this file previously pinned) and privilege escalation to
# proxy admin via cross-domain reuse of the salt key (CVE-2026-114612 /
# GHSA-7hp6-4w63-5g45, fixed 1.103.1; no 1.96.x fix). The SSRF one is the
# sharpest for Triple-C: this container holds a billed provider key. v1.106.6 is
# the newest stable release with no open OSV advisories at the time of writing
# (2026-11-02), and its digest was checked with
# `cosign verify --key https://raw.githubusercontent.com/BerriAI/litellm/e82a3c646908ba0a6ee0beddc4310d7a6cac4065/cosign.pub`.
# Note LiteLLM has retired the `main-*` tag family (`main-latest` is no longer
# updated, `main-stable` is deprecated) in favour of plain semver tags, which is
# why this is `v1.106.6` and not `main-v1.106.6-stable`.
#
# Bump deliberately, never automatically, and re-check the digest when you do.
FROM ghcr.io/berriai/litellm:v1.106.6@sha256:37e2dafb088a7723beb998590682957386dfc83ffea1848486f8e0e5cfac0b06
# A placeholder config so the image is runnable on its own. Triple-C overwrites
# /etc/litellm/config.yaml (a named volume) with the generated one before the
# container is started for the first time — the generated file holds the
# provider API key, so it is never baked into an image layer.
COPY config.yaml /etc/litellm/config.yaml
EXPOSE 4000
# The base image's ENTRYPOINT is `docker/prod_entrypoint.sh`, which execs
# `litellm "$@"`. These are the arguments Triple-C also passes explicitly when
# it runs the unmodified upstream image instead of this one.
CMD ["--config", "/etc/litellm/config.yaml", "--host", "0.0.0.0", "--port", "4000"]