Blinda el teu gateway de LLM

AlamedaDev Team27 d'octubre de 2026

I com blindar la seva cadena de subministrament abans que la propera release enverinada arribi al teu pip install.

Actualització (27 d'octubre de 2026). LiteLLM va publicar el 23 d'octubre la seva anàlisi de la causa arrel definitiva de l'incident de la 1.107.0, i corregeix la seva hipòtesi inicial: el primer esglaó no van ser els logs d'un gateway, sinó una clau mestra filtrada en un repositori públic al maig i mai revocada. Hem actualitzat la secció 2.3 i els controls afectats. Sobre la vulnerabilitat la divulgació de la qual LiteLLM havia programat per al 27 d'octubre: a les 21:00 (hora peninsular) d'aquell dia encara no hi havia cap avís de seguretat publicat que la identifiqui. Aquell mateix dia van sortir les versions de pegat 1.103.10, 1.104.8, 1.105.6 i 1.106.5 amb un canvi marcat com a correcció de seguretat en els logs de peticions rebutjades (PR #48599). LiteLLM no ho ha vinculat públicament a l'embargament, així que no ho donem per fet.

El 21 d'octubre de 2026, algú va executar pip install litellm sense fixar versió, o va arrencar un contenidor amb l'etiqueta latest. No va importar la llibreria ni va aixecar el proxy. Li va bastar que Python arrenqués en aquell entorn perquè un recol·lector de credencials comencés a llegir claus de proveïdors de models, credencials del núvol, tokens de GitHub, configuració d'eines d'IA i servidors MCP, i les enviés xifrades a un domini que imitava l'oficial.

No és un supòsit. És el que descriuen els mateixos mantenidors de LiteLLM i l'equip de Microsoft Security Research sobre la versió 1.107.0, publicada amb malware a PyPI i a les imatges oficials de contenidor. Vuit dies abans, Check Point Research havia publicat dues vulnerabilitats greus en el mateix gateway. I al març, el mateix projecte ja havia patit un altre compromís de la seva cadena de publicació.

Aquest és el segon post de la nostra sèrie sobre bones pràctiques en el desenvolupament de productes d'IA. El primer va tractar la seguretat dels agents davant de la prompt injection; avui baixem una capa, a la infraestructura que gairebé ningú revisa perquè "només és un proxy". No escrivim això per assenyalar LiteLLM: és un projecte útil, ha respost amb transparència i el que li ha passat li pot passar a qualsevol dependència del teu stack. L'utilitzem perquè és el cas més clar i recent d'un patró que afecta tots els equips que porten IA a producció.

1. Què és un gateway de LLM i per què concentra tant de risc

Un gateway de LLM se situa entre les teves aplicacions i els proveïdors de models. En lloc que cada servei cridi directament a OpenAI, Anthropic o Google, totes les peticions passen per una capa que centralitza les credencials, l'encaminament entre models, els fallbacks, els límits d'ús, el registre de peticions i el control de despesa. LiteLLM, Portkey, les passarel·les dels proveïdors cloud o una implementació pròpia compleixen aquest paper.

És una bona idea d'arquitectura: evita repartir API keys per deu serveis i et dóna un únic punt d'observabilitat i control de costos. Però aquest punt únic té una conseqüència que convé dir en veu alta: el gateway és, per disseny, el lloc on estan totes les claus. Microsoft ho resumeix així en la seva anàlisi de l'incident: en aquesta posició, el gateway pot tenir accés a les API keys dels proveïdors, cadenes de connexió a base de dades, identitats de càrrega de treball, configuració d'encaminament i dades de polítiques per client.

A això s'hi sumen dues propietats que el fan més delicat que qualsevol microservei:

  • Veu tot el trànsit. Prompts, respostes, documents recuperats per RAG, dades personals que l'usuari enganxa en un xat. Si registra cossos complets, els seus logs són una còpia de tot això.
  • La mateixa dependència viu a molts llocs. El paquet no només corre al servidor del proxy: també a portàtils de desenvolupament, agents de CI, entorns de test i notebooks. Microsoft subratlla precisament que això va ampliar el conjunt d'entorns exposats.

Amb això al cap, vegem el que ha passat les últimes setmanes.

2. Tres incidents en un mes, tres lliçons diferents

2.1 13 d'octubre: control d'accés trencat al propi gateway

Check Point Research va publicar dues vulnerabilitats a LiteLLM (analitzades sobre la versió 1.77.7 i corregides a partir de la 1.83.9):

  • CVE-2026-35029: l'endpoint administratiu POST /config/update no comprovava el rol de l'usuari. Qualsevol usuari autenticat, inclòs un de només lectura, podia modificar la configuració en calent. A partir d'aquí, els investigadors van demostrar lectura arbitrària de fitxers, presa de control del compte d'administrador i execució remota de codi carregant un mòdul Python des d'un bucket.
  • CVE-2026-59823: una SSRF a la funció de credencials del costat del client permetia redirigir les trucades del gateway a un servidor de l'atacant i capturar les API keys del proveïdor.

El detall tècnic més instructiu de la primera és com es colava la petició: la llista de rutes permeses per a sessions de la interfície web incloïa /config (probablement pensada per llegir la configuració), i la comprovació feia servir startswith. /config/update comença per /config, així que passava. Check Point ho resumeix en la seva conclusió: no són classes d'atac noves, sinó fallades de control d'accés i validació d'entrades ben conegudes.

Lliçó: el gateway és software de backend amb un panell d'administració, i s'hi aplica tot el que ja sabeu de seguretat web. No l'exposeu a internet "perquè és intern", i no doneu comptes d'usuari a qui no els necessita.

2.2 20 d'octubre: el servidor d'inferència també és superfície

El mateix mes, vLLM va publicar l'avís GHSA-6757-hggm-hp2w: en desplejaments amb la memòria cau multimodal en memòria compartida activada (--mm-processor-cache-type shm), un usuari autenticat de l'API d'inferència podia forjar una referència que acabava en un pickle.loads() al worker, és a dir, execució de codi arbitrari. Afecta versions fins a la 0.25.1 i està corregit a la 0.32.0.

Lliçó: si autoallotgeu models, "autenticat" no equival a "de confiança". Una API key d'inferència que lliureu a un client o a un altre equip pot ser suficient per executar codi a les vostres GPUs si no esteu al dia amb els pegats.

2.3 21 d'octubre: la release enverinada

Aquest és l'incident que dóna títol al post. Segons la pàgina d'incident de LiteLLM:

  • litellm==1.107.0 va estar publicada a PyPI amb malware durant unes dues hores (de 11:39 a 13:23 UTC).
  • Les etiquetes Docker v1.107.0, latest, main-latest i main-stable van apuntar a una imatge compromesa entre les 11:46 i les 14:20 UTC.
  • El tag de codi font oficial no contenia els fitxers maliciosos: els artefactes es van construir des d'un repositori de l'atacant amb un nom gairebé idèntic (Berri-AI/litellm en lloc de BerriAI/litellm).

El més incòmode és com va arribar-hi. Després de l'incident de març, l'equip havia endurit el seu pipeline: releases des d'un repositori privat, publicació amb Trusted Publishers, etiquetes Docker immutables i imatges signades. La seva anàlisi de la causa arrel, publicada el 23 d'octubre i que ells mateixos presenten com la font canònica, reconstrueix la cadena completa:

  1. 27 de maig. Es puja per error a un repositori públic un fitxer de configuració amb la clau mestra d'un desplejament de LiteLLM Agent Platform, una eina pròpia per orquestrar agents. El commit es va sobreescriure, però la clau mestra mai es va revocar.
  2. 10 d'octubre. L'atacant utilitza aquesta clau contra l'API de la plataforma. Una petició que llista els agents configurats retorna el token OAuth de la CLI de GitHub d'un dels dos propietaris de l'organització: era el token amb el qual els agents obrien PRs, personal, sense acotar i no associat a un compte de servei.
  3. 10 i 12 d'octubre. Amb aquest token, l'atacant puja branques d'usar i llençar els workflows de CI de les quals envien els secrets dels repositoris a un endpoint extern. Així obté els tokens d'altres dos mantenidors, guardats com a secrets de CI, i esborra després aquestes execucions.
  4. 21 d'octubre. Amb el token del propietari es salta la protecció de branques i apunta el workflow de release al repositori clonat (Berri-AI/litellm). Aquella mateixa setmana s'havia relaxat temporalment l'aprovació de producció per permetre backports més freqüents: en bastaven dos enginyers qualsevol. Amb el segon token aprova la publicació i amb el tercer esborra els registres de les execucions. El pipeline legítim va signar i publicar els artefactes maliciosos.

La primera hipòtesi, publicada durant l'incident, apuntava a tokens que un assistent de programació havia inclòs en respostes registrades als logs d'un desplejament intern de LiteLLM exposat a internet. L'anàlisi final la descarta per a aquest cas: els logs de peticions mostren que el primer token va sortir d'un altre servei, l'API de la plataforma d'agents.

És a dir: una clau filtrada cinc mesos abans i mai revocada, en una plataforma d'agents que guardava i retornava un token de GitHub amb permisos de propietari, va ser el primer esglaó per comprometre la cadena de publicació del propi gateway. Cap peça és exòtica per separat; el problema va ser la suma.

L'anàlisi de Microsoft afegeix el detall tècnic que explica per què el radi d'impacte va ser tan gran. El paquet instal·lava cook.pth, cook.py i sitecustomize.py fora del directori de la llibreria. Python processa els fitxers .pth i sitecustomize a cada arrencada de l'intèrpret, així que no feia falta importar LiteLLM: en un cas observat a Windows, una invocació rutinària de Python per instal·lar una dependència aliena va activar el recol·lector. Aquest recol·lector buscava configuració d'assistents d'IA, IDEs i integracions MCP, credencials d'AWS, Azure i Google Cloud (inclosos els endpoints de metadades), tokens de Kubernetes, claus SSH, dades de navegadors, variables d'entorn d'altres processos i registres de credencials de la base de dades del proxy. A més, en sistemes Unix deixava un carregador capaç de descarregar i executar codi addicional des d'un servidor controlat per l'atacant.

L'incident de març va seguir un patró semblant per una altra porta. Les versions 1.82.7 i 1.82.8 es van publicar amb un lladre de credencials, i la investigació apunta que l'origen va ser Trivy, l'escàner de seguretat que utilitzaven en CI. Segons JFrog, l'script del pipeline instal·lava Trivy amb apt-get install trivy sense fixar versió ni verificar checksum, així que va descarregar automàticament una release maliciosa de l'escàner, que es va endur els tokens de publicació. Un detall rellevant: LiteLLM va indicar que els usuaris de la seva imatge Docker oficial no es van veure afectats al març perquè aquesta via fixava dependències a requirements.txt.

3. El que aquests incidents ensenyen (més enllà de LiteLLM)

Quatre idees que apliquem en qualsevol revisió d'arquitectura d'un producte d'IA:

  1. Signar no és verificar l'origen. A l'octubre, els artefactes estaven signats pel pipeline legítim. La signatura demostra qui va construir l'artefacte, no des de quin codi. Cal verificar també la procedència (repositori i commit d'origen) i, sobretot, no acceptar versions noves a cegues.
  2. Les etiquetes mutables són una porta oberta. latest i main-stable van apuntar durant hores a una imatge maliciosa. Qui desplegava per digest o tenia fixada una versió anterior no va rebre res. Les versions fixades amb hash no eviten que un projecte sigui compromès, però sí que el compromís arribi només a la teva producció.
  3. Les eines de seguretat i d'IA són objectius preferents. Endor Labs assenyala que la campanya de març va apuntar deliberadament a eines properes a la seguretat (Trivy, KICS) i després a un proxy de LLM, perquè corren en entorns plens de credencials. Un gateway d'IA, un escàner en CI o un servidor MCP al portàtil del desenvolupador són exactament aquest tipus d'entorn.
  4. Les credencials dels agents són credencials de producció. El primer token robat a l'octubre no estava en un servidor de producció, sinó en la configuració d'una plataforma interna d'agents, i era un token personal amb permisos de propietari. Si un agent necessita obrir PRs, doneu-li un compte de servei o una GitHub App amb permisos mínims i credencials de curta durada, i no deixeu que cap API retorni secrets en clar. És el mateix mínim privilegi que tractem al primer post de la sèrie, aplicat a la infraestructura.

OWASP ho recull com a LLM03:2025 Supply Chain al seu Top 10 per a aplicacions LLM: a més dels riscos clàssics de paquets de tercers, la cadena de subministrament en IA inclou models preentrenats, adaptadors LoRA, plataformes de desplegament i els termes d'ús dels proveïdors. Entre les seves mitigacions proposa mantenir un inventari signat i actualitzat de components (SBOM) i avaluar els AI BOM o ML-BOM començant per CycloneDX.

4. Set controls que aplicaríem aquesta setmana

Ordenats de més barat a més costós. Els quatre primers es fan en una tarda.

4.1 Versions fixades amb hash, també en CI

Un requirements.txt amb litellm>=1.80 o un pip install litellm en un Dockerfile significa "instal·la l'últim que hagi publicat qui controli aquest compte avui". Fixeu versió i hash de cada artefacte. Amb pip, el mode de verificació de hashes és tot o res: si una sola línia porta --hash, s'exigeix per a totes.

# Generar requirements amb hashes (uv o pip-tools)
uv pip compile requirements.in --generate-hashes -o requirements.txt

# Instal·lar exigint hashes i sense compilar paquets des de codi font
pip install --require-hashes --only-binary :all: -r requirements.txt

Si useu uv amb projectes, uv.lock ja registra els hashes; l'important és que CI i els Dockerfiles instal·lin des del lockfile i fallin si no està sincronitzat:

uv sync --locked   # falla si uv.lock no coincideix amb pyproject.toml

I el mateix per a les eines del pipeline: el compromís de març va entrar per un escàner instal·lat sense versió. Les Actions de GitHub, fixades al SHA complet del commit, tal com recomana la pròpia guia de seguretat de GitHub Actions:

# Malament: l'etiqueta v4 la pot moure qui controli el repositori
- uses: actions/checkout@v4
# Bé: SHA complet del commit, amb la versió com a comentari
- uses: actions/checkout@<sha-complet-de-40-caràcters> # v4.x.y

4.2 Imatges per digest, mai per etiqueta flotant

# Malament
FROM ghcr.io/berriai/litellm:main-stable

# Bé: el digest identifica contingut immutable
FROM ghcr.io/berriai/litellm@sha256:<digest-verificat>

El mateix als manifestos de Kubernetes i a Helm. Microsoft ho inclou explícitament en les seves recomanacions: els digests són preferibles a les etiquetes mutables perquè identifiquen contingut immutable.

4.3 Quarantena per a versions noves

Els dos compromisos de LiteLLM van estar disponibles unes hores (uns 40 minuts al març; unes dues hores a PyPI a l'octubre). Un retard d'uns dies abans d'acceptar una versió nova hauria evitat instal·lar qualsevol dels dos. Hi ha eines que ho fan de forma nativa:

# pyproject.toml — uv només considera artefactes pujats fa més de 7 dies
# (les durades relatives requereixen una versió recent de uv)
[tool.uv]
exclude-newer = "7 days"
# .github/dependabot.yml — no proposar versions amb menys de 7 dies
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 7
      semver-major-days: 14

Dependabot aplica per defecte un cooldown de 3 dies a les actualitzacions de versió, i aquesta espera no afecta les actualitzacions de seguretat, que és justament el que voleu: els pegats crítics (com l'1.83.9 de LiteLLM) entren ràpid i la resta espera que la comunitat hagi tingut temps de detectar res estrany.

4.4 Vigilar els ganxos d'arrencada de Python

El malware d'octubre (i la versió 1.82.8 de març) va utilitzar fitxers .pth amb línies import, que Python executa en arrencar. Python 3.15 ja ha marcat aquestes línies com a obsoletes, però es continuen executant i continuaran existint als entorns actuals durant anys. Un control barat és fixar una línia base de quins fitxers .pth executables i sitecustomize.py existeixen a les vostres imatges, i fer fallar el build si n'apareix un de nou:

#!/usr/bin/env sh
# check-startup-hooks.sh — no invoca Python a propòsit: si l'entorn
# estigués compromès, arrencar l'intèrpret executaria el payload.
SITE_DIRS="${SITE_DIRS:-/usr/local/lib /opt/venv/lib}"

found=$(
  find $SITE_DIRS \( -name '*.pth' -o -name 'sitecustomize.py' -o -name 'usercustomize.py' \) 2>/dev/null |
  while read -r f; do
    case "$f" in
      *.pth) grep -qE '^import[[:space:]]' "$f" && echo "$f" ;;
      *)     echo "$f" ;;
    esac
  done | sort
)

# allowlist revisada a mà (alguns paquets legítims utilitzen .pth executables)
if ! echo "$found" | diff -u startup-hooks.allowlist - ; then
  echo "Nou ganxo d'arrencada de Python detectat. Revisar abans de desplegar." >&2
  exit 1
fi

No substitueix un escàner de malware, però converteix la tècnica concreta que s'ha utilitzat dues vegades enguany en una alerta de CI.

4.5 Aïllar el gateway i tancar la seva sortida a internet

El gateway necessita parlar amb un grapat de hosts coneguts (els endpoints dels vostres proveïdors de models, la base de dades, el sistema d'observabilitat). No necessita parlar amb res més. Si el recol·lector d'octubre no hagués pogut fer el seu POST al domini de l'atacant, el robatori de credencials no hauria sortit del host. Microsoft recomana que estacions de treball, agents de build, entorns de test i hosts de gateways d'IA no tinguin accés HTTP de sortida sense restriccions, sinó que passin per controls d'egress amb allowlist.

A la pràctica:

  • El panell d'administració i els endpoints de gestió (/config, /key, /user...) no es publiquen a internet. Accés per VPN o xarxa privada, i només per als administradors.
  • Sortida a internet només a través d'un proxy d'egress amb allowlist de dominis, aplicada a nivell de xarxa (les NetworkPolicy de Kubernetes treballen amb IPs i selectors, no amb dominis, així que per filtrar per nom de host cal un proxy de sortida o un CNI que ho suporti).
  • Bloquejar l'accés a l'endpoint de metadades del núvol (169.254.169.254) des del contenidor del gateway si no ho necessita, o exigir IMDSv2 a AWS. El recol·lector d'octubre intentava obtenir credencials d'allà.

4.6 Logs del gateway sense secrets i amb retenció curta

La primera hipòtesi de LiteLLM sobre l'octubre apuntava a tokens que havien acabat als logs del seu gateway. L'anàlisi final la va descartar per a aquest cas, però el risc està documentat: al març, el propi projecte va publicar un incident en el qual les respostes de guardarrails personalitzats podien portar capçaleres Authorization en clar als spend logs i a les traces d'OpenTelemetry. I el 27 d'octubre va publicar una correcció de seguretat perquè els logs de peticions rebutjades es construeixin a partir d'una llista tancada de camps: fins llavors es generaven directament des del cos de la petició, i qui trucava podia influir en on anava aquest log. Registrar cossos complets de peticions i respostes és temptador per depurar, però converteix els vostres logs en un magatzem de prompts, dades personals i, de vegades, credencials.

  • Desactiveu el registre de cossos complets per defecte; activeu-lo només de manera temporal i acotada.
  • Redacteu patrons de secrets abans de persistir (tokens ghp_/gho_, sk-, AKIA, JWTs, capçaleres Authorization).
  • Retenció curta i accés restringit als logs. Si la vostra eina d'observabilitat de LLM guarda traces completes, apliqueu-li la mateixa política (de l'observabilitat en parlem en aquest post).

Bonus de disseny: si escriviu el vostre propi control d'accés (al gateway o en qualsevol API), compareu rutes i permisos de manera exacta o per patrons explícits, mai per prefix:

# Malament: "/config/update".startswith("/config") és True
READ_ONLY_UI_ROUTES = ["/config", "/spend", "/key/info"]
def allowed(route: str) -> bool:
    return any(route.startswith(r) for r in READ_ONLY_UI_ROUTES)

# Millor: rutes exactes i mètode explícit; tot el que és administratiu exigeix rol
READ_ONLY_UI_ROUTES = {("GET", "/config"), ("GET", "/spend"), ("GET", "/key/info")}
def allowed(method: str, route: str, role: str) -> bool:
    if (method, route) in READ_ONLY_UI_ROUTES:
        return True
    return role == "admin"

4.7 Inventari (AIBOM) i pla de rotació assajat

Quan surt un avís com el d'octubre, la primera pregunta és "estem afectats?". Si la resposta requereix preguntar a Slack a cada equip, arribeu tard. Microsoft demana localitzar la versió compromesa en entorns instal·lats, memòries cau de uv i pip, mirrors interns, lockfiles, artefactes de build i imatges. Això només és ràpid si teniu inventari.

Un inventari mínim per a un producte d'IA hauria d'incloure, per servei i entorn:

ComponentQuè registrar
Gateway de LLMVersió exacta, digest d'imatge, on corre, quins secrets té muntats
SDKs i frameworks (LLM, agents, RAG)Versió i hash des del lockfile
Servidors d'inferència propisVersió, flags rellevants (p. ex. memòries cau compartides), exposició de xarxa
ModelsProveïdor i identificador de versió; si són pesos propis o de tercers, origen i hash
Servidors MCP i einesOrigen, versió fixada, permisos i credencials que utilitzen
Eines de CIVersió fixada d'escàners, Actions per SHA

CycloneDX té un format específic per a això (ML-BOM), i OWASP ho suggereix com a punt de partida. Però no espereu a l'eina perfecta: una taula generada des dels vostres lockfiles i manifestos ja respon a gairebé tot el que necessiteu saber quan pregunteu "on tenim això?".

L'altra meitat és la rotació, i comença abans de l'incident: la cadena d'octubre va arrencar amb una clau exposada al maig el commit de la qual es va sobreescriure però que mai es va revocar. Esborrar un secret de l'historial no l'invalida; cal revocar-lo i comprovar que la revocació ha tingut efecte. Per a la resposta a un incident, la guia de LiteLLM per a afectats demana rotar el rol IAM de la instància, totes les claus de proveïdor guardades a la base de dades del proxy, les claus mestres i virtuals, la contrasenya de la base de dades i qualsevol secret de l'entorn de qualsevol procés del host. Microsoft afegeix revocar sessions actives, perquè rotar una contrasenya no invalida automàticament tots els tokens emesos. Si mai no heu rotat les vostres claus de proveïdor de models, feu l'assaig ara, amb calma, i no a les tres de la tarda d'un dimarts amb un incident obert. I preferiu identitats de càrrega de treball amb credencials de curta durada davant de claus estàtiques sempre que el proveïdor ho permeti.

5. Dos errors que desfan tot l'anterior

Error 1: "fem servir la imatge oficial, així que estem salvats". A l'octubre, la imatge oficial amb l'etiqueta main-stable era la compromesa. Oficial i signada no significa revisada per vosaltres. El que us protegeix és fixar per digest, endarrerir l'adopció de versions noves i limitar el que el contenidor pot assolir si alguna cosa va malament.

Error 2 (el contrapès): congelar dependències i no actualitzar mai. Les vulnerabilitats de Check Point estaven corregides en la 1.83.9; qui seguís en una versió anterior per "estabilitat" tenia un gateway que qualsevol usuari autenticat podia prendre. Fixar versions no és el mateix que no actualitzar: és actualitzar de manera deliberada, amb una quarantena per al nou i una via ràpida per als pegats de seguretat.

Checklist: gateway de LLM i cadena de subministrament abans d'anar a producció

Dependències i artefactes

  • [ ] Totes les dependències Python s'instal·len des d'un lockfile amb hashes (--require-hashes o uv sync --locked), també a CI i Dockerfiles.
  • [ ] Cap imatge es desplega per etiqueta flotant (latest, main-stable); totes per digest.
  • [ ] Les GitHub Actions estan fixades a SHA complet i les eines de CI (escàners inclosos) tenen versió fixada.
  • [ ] Hi ha quarantena per a versions noves (exclude-newer, cooldown de Dependabot o equivalent) i una via ràpida documentada per a pegats de seguretat.
  • [ ] El build falla si apareix un .pth executable o un sitecustomize.py no inclòs a l'allowlist.

Gateway i inferència

  • [ ] El panell i els endpoints d'administració del gateway no són accessibles des d'internet.
  • [ ] Els comptes del gateway segueixen el mínim privilegi i es revisen periòdicament (sense usuaris "de prova" oblidats).
  • [ ] El gateway i els servidors d'inferència estan en una versió sense vulnerabilitats conegudes (comprovat contra els avisos del projecte).
  • [ ] La sortida a internet del gateway passa per un egress amb allowlist, i l'endpoint de metadades del núvol està bloquejat o restringit.
  • [ ] Cada aplicació fa servir la seva pròpia clau virtual amb límits de despesa; les claus de proveïdor no surten del gateway.

Logs i secrets

  • [ ] El gateway no registra cossos complets per defecte i redacta secrets abans de persistir.
  • [ ] Els logs i traces de LLM tenen retenció curta i accés restringit.
  • [ ] Les credencials són de curta durada (identitats de càrrega de treball) sempre que sigui possible.
  • [ ] Qualsevol secret exposat (en un repositori, un log o un tiquet) es revoca immediatament, no només s'esborra, i es verifica la revocació.
  • [ ] Els agents i els workflows de CI fan servir comptes de servei o GitHub Apps amb permisos mínims, mai tokens personals d'administradors.

Resposta

  • [ ] Existeix un inventari (AIBOM) que respon en minuts "on corre la versió X d'aquest component?".
  • [ ] Hi ha un runbook de rotació de claus de proveïdors de models, núvol, base de dades i CI, i s'ha assajat almenys una vegada.
  • [ ] El runbook indica investigar entorns sospitosos des de fora, sense executar python ni pip a dins.
  • [ ] Algú de l'equip segueix els avisos de seguretat de les dependències crítiques d'IA (gateway, servidor d'inferència, SDKs, servidors MCP).

Conclusió

El gateway de LLM és una de les millors decisions d'arquitectura que pot prendre un producte d'IA: centralitza claus, costos i observabilitat. Precisament per això és el component que més mereix un tractament d'infraestructura crítica, no de "proxy que muntem en una tarda".

El que han mostrat aquestes setmanes no és que una eina concreta sigui insegura, sinó que la cadena que porta codi de tercers fins a la vostra producció té molts esglaons, i en basta un: una clau filtrada que ningú va revocar, un token de propietari en la configuració d'un agent, un escàner sense versió fixada, una etiqueta que apunta a un altre lloc. Cap dels controls d'aquest post és exòtic. Són pràctiques d'enginyeria de software de tota la vida aplicades a la part del stack que més ràpid s'està muntant i que menys es revisa.

La setmana que ve continuem amb una altra peça que sol quedar-se fora de les demos. Si teniu un gateway o un servidor d'inferència en producció i voleu revisar la seva exposició i la seva cadena de subministrament, estarem encantats de tenir aquesta conversa. Sense pitch: una trucada de 30 minuts amb un dels nostres enginyers.

Fonts

  1. LiteLLM. Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised (21 oct. 2026, actualitzat el 23 oct.). https://docs.litellm.ai/blog/security-incident-oct-21-2026
  2. Microsoft Security Research. Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks (23 oct. 2026). https://www.microsoft.com/en-us/security/blog/2026/10/23/inside-the-litellm-1-107-0-supply-chain-compromise-credential-theft-through-python-startup-hooks/
  3. Check Point Research. When LLM Gateways Go Wrong: Findings from LiteLLM (13 oct. 2026). CVE-2026-35029, CVE-2026-59823. https://research.checkpoint.com/2026/when-llm-gateways-go-wrong-findings-from-litellm/
  4. Check Point. Check Point Research Discovers High Risk Vulnerabilities in LiteLLM, One of the Most Widely Used LLM Gateways (13 oct. 2026). https://blog.checkpoint.com/security/check-point-research-discovers-high-risk-vulnerabilities-in-litellm-one-of-the-most-widely-used-llm-gateways/
  5. vLLM. GHSA-6757-hggm-hp2w: Public multimodal SHM handle forgery reaches worker-side pickle.loads() (20 oct. 2026). https://github.com/vllm-project/vllm/security/advisories/GHSA-6757-hggm-hp2w
  6. LiteLLM. Security Update: Suspected Supply Chain Incident (març 2026). https://docs.litellm.ai/blog/security-update-march-2026
  7. JFrog Security Research. Popular litellm Python package is the latest victim of TeamPCP's ongoing supply chain attack (març 2026). https://research.jfrog.com/post/litellm-compromised-teampcp/
  8. Datadog Security Labs. LiteLLM and Telnyx compromised on PyPI: Tracing the TeamPCP supply chain campaign (2026). https://securitylabs.datadoghq.com/articles/litellm-compromised-pypi-teampcp-supply-chain-campaign/
  9. Endor Labs. TeamPCP Isn't Done: Threat Actor Behind Trivy and KICS Compromises Now Hits LiteLLM (24 març 2026). https://www.endorlabs.com/learn/teampcp-isnt-done
  10. OWASP Gen AI Security Project. LLM03:2025 Supply Chain. https://genai.owasp.org/llmrisk/llm032025-supply-chain/
  11. CycloneDX. Machine Learning Bill of Materials (AI/ML-BOM). https://cyclonedx.org/capabilities/mlbom/
  12. Python documentation. site — Site-specific configuration hook (fitxers .pth, sitecustomize, obsolescència de línies import a 3.15). https://docs.python.org/3/library/site.html
  13. pip documentation. Secure installs (hash-checking mode, --require-hashes, --only-binary). https://pip.pypa.io/en/stable/topics/secure-installs/
  14. uv documentation. Settings: exclude-newer. https://docs.astral.sh/uv/reference/settings/#exclude-newer · Locking and syncing. https://docs.astral.sh/uv/concepts/projects/sync/
  15. GitHub Docs. Dependabot options reference: cooldown. https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference
  16. GitHub Docs. Secure use reference (fixar Actions a SHA complet). https://docs.github.com/en/actions/reference/security/secure-use
  17. PyPI Docs. Trusted Publishers. https://docs.pypi.org/trusted-publishers/ · Attestations. https://docs.pypi.org/attestations/
  18. LiteLLM. The attack chain behind the v1.107.0 LiteLLM release (anàlisi de la causa arrel, 23 oct. 2026). https://docs.litellm.ai/blog/security-incident-oct-21-2026-attack-chain
  19. LiteLLM. Incident Report: Guardrail logging exposed secret headers in spend logs and traces (18 març 2026). https://docs.litellm.ai/blog/guardrail-logging-secret-exposure-incident
  20. LiteLLM. PR #48599, fix(security)!: build proxy-only failure logs from an allowlist and drop caller guardrail info (27 oct. 2026), inclòs a v1.103.10, v1.104.8, v1.105.6 i v1.106.5. https://github.com/BerriAI/litellm/pull/48599 · https://github.com/BerriAI/litellm/releases/tag/v1.106.5