
MaxKB a attaché un outil Shell à chaque assistant doté d’outils, sans jamais en restreindre l’accès
- OrcaNOUVEAUOrcaCyber: GLM 5.3 Flash Abliterated2026-10-2796 tok/s
- OrcaNOUVEAUOrcaCyber: Qwen3.8 Flash Next Abliterated2026-10-26$0.80 / $1.60 par million de tokens · 252 tok/s
- OrcaNOUVEAUOrcaCyber: MiMo V2.6 Flash Abliterated2026-10-26$0.80 / $1.60 par million de tokens · 89 tok/s
- MoonshotNOUVEAUMoonshotAI: Kimi K3.1 Pro2026-10-2446Intelligence
- OrcaNOUVEAUOrcaCyber: DeepSeek V4.1 Flash Abliterated2026-10-23$0.80 / $1.60 par million de tokens · 107 tok/s
- minimaxNOUVEAUMiniMax: M3.1 Flash2026-10-1929Intelligence
- OrcaNOUVEAUOrca: OrcaCyber Ultra 1.02026-10-17$5.00 / $10.00 par million de tokens · 53 tok/s
- deepseekNOUVEAUDeepSeek: DeepSeek V4.1 Flash 10172026-10-1733Intelligence
- DeepSeekNOUVEAUDeepSeek: DeepSeek V4.1 Flash2026-10-1740Intelligence
- OrcaOrca: OrcaCyber Zero 1.52026-10-10$3.00 / $7.50 par million de tokens · 116 tok/s
- openaiOpenAI: GPT-6.1 Sol2026-09-2955Intelligence
- anthropicAnthropic: Claude Sonnet 5.52026-09-2854Intelligence
- typesafeTypeSafe: Jev 1.132026-09-24$0.04 / $0.00 par million de tokens · 140 tok/s
- OpenAIOpenAI: GPT-6 Luna2026-09-2228Intelligence
- OpenAIOpenAI: GPT-6 Sol2026-09-2248Intelligence
- AnthropicAnthropic: Claude Opus 5.52026-09-2258Intelligence
- xiaomiXiaomi: MiMo-V2.6-Flash2026-09-2127Intelligence
- xiaomiXiaomi: MiMo-V2.6-Pro2026-09-2130Intelligence
- xAIGrok 4.72026-09-2134Intelligence
- OrcaOrca: OrcaCyber Zero 1.02026-09-17$3.00 / $7.50 par million de tokens · 182 tok/s
MaxKB, plateforme d'assistant d'entreprise open source publiée sous l'organisation GitHub 1Panel-dev, a bâti ses agents conversationnels sur un framework qui ajoute silencieusement un outil shell dès qu'un backend capable de shell est fourni — et MaxKB n'a jamais retiré cet outil ni demandé à quiconque d'approuver son utilisation. La faille est CVE-2026-77521, publiée comme avis GitHub GHSA-f36j-f34j-h3rx le 2 septembre 2026 et notée 10,0 sur 10 selon le CVSS 3.1 dans le cas d'un assistant public ou intégré. Lasso Security, qui l'a découverte et signalée, a démontré qu'un message de discussion — ou un texte que l'assistant ne fait qu'ingérer via la recherche documentaire ou un document téléversé — pouvait amener le modèle à exécuter des commandes : sur un déploiement bare-metal directement sur l'hôte, et sur le conteneur officiel via un wrapper que les chercheurs jugent contournable avec un point-virgule. Aucune source citée ne rapporte d'exploitation de la faille dans la nature. La note de gravité, l'évaluation de confiance et la liste des sources propres à la fiche figurent dans l'archive des incidents d'IA, aux côtés des entrées voisines consacrées à MaxKB et aux outils d'agents issues du même lot de divulgations.
MaxKB est un produit auto-hébergé permettant de créer des assistants augmentés par récupération d’informations : un opérateur crée un assistant, lui attache des capacités — outils, serveurs Model Context Protocol, compétences, sous-applications —, connecte une base de connaissances constituée de documents téléversés ou de sites web explorés, puis expose l’assistant soit via une console authentifiée, soit sous forme de widget de chat public et intégrable. C’est précisément cette polyvalence qui constitue la surface d’exposition. La condition de déclenchement de l’avis de sécurité n’est pas une configuration inhabituelle, mais la configuration ordinaire : tout assistant auquel au moins une capacité est attachée achemine son chat via le chemin d’agent concerné, tandis qu’un chat sans aucune capacité attachée ne le fait pas. L’analyse de Lasso décrit le projet comme l’un des plus largement adoptés dans sa catégorie et note que MaxKB est normalement déployé comme un service multi-tenant — ce qui place une commande s’exécutant sous l’utilisateur de l’application en dessous du modèle de location, plutôt qu’à l’intérieur du segment d’un locataire donné.
L’outil shell est arrivé avec le framework, pas avec le produit
MaxKB construit ces agents avec la bibliothèque deepagents de LangChain, épinglée à la version 0.6.11 dans le pyproject.toml du projet, à la fois sur l’étiquette vulnérable et sur l’actuelle. Dans apps/application/flow/tools.py, à la ligne 467 de l’étiquette v2.10.3-lts, le projet appelle create_deep_agent avec backend défini sur SandboxShellBackend, une sous-classe de MaxKB qui exécute des commandes sur l’hôte. Selon l’avis, deepagents injecte automatiquement un ensemble d’outils chaque fois qu’un backend shell est transmis de cette manière : execute, ls, read_file, write_file, edit_file, glob et grep. Ils ne font pas partie de l’argument tools=list, qui ne contient que les outils propres à l’opérateur, les outils MCP et les outils de compétence. Ils ne peuvent pas être supprimés de l’interface ni par la configuration.
MaxKB ne transmet pas non plus excluded_tools, l’argument de la bibliothèque qui les supprimerait. L’avis prend soin d’expliquer pourquoi cela importe, même à titre de remède : excluded_tools « retire l’outil de ce qui est indiqué au modèle, pas de l’exécuteur ». La distinction entre un outil dont le modèle n’a pas connaissance et un outil qui ne peut pas s’exécuter, c’est tout ce bug en miniature.
Une porte qui répertorie trois outils et omet le quatrième
Le contrôle human-in-the-loop dans ce même appel tient en une ligne, et il énumère trois opérations : interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. L’écriture d’un fichier, la lecture d’un fichier et la modification d’un fichier sont nommées. L’exécution de commandes ne figure pas du tout comme clé dans le dictionnaire. Selon l’interprétation de l’avis, cela signifie qu’aucune approbation n’est demandée pour execute — les trois opérations de système de fichiers sont nommées et explicitement définies pour ne pas interrompre, et l’outil shell n’est pas nommé du tout.
Mis bout à bout, le scénario est le suivant : un texte non fiable atteint le modèle, le modèle appelle execute et la commande s’exécute. L’avis identifie deux manières pour un texte non fiable d’arriver. La voie directe est le chat — un widget public ou intégré, ou la conversation d’un autre locataire. La voie indirecte est le contenu que l’assistant ingère : un document RAG, un fichier téléversé ou une page web que la plateforme explore pour l’intégrer à une base de connaissances. Le billet de Lasso rend la seconde voie concrète, en faisant remarquer que « l’ensemble des personnes qui peuvent placer du texte devant le modèle est plus grand que l’ensemble des personnes qui peuvent discuter avec lui ».
Sur une installation bare-metal, la commande n'est qu'une commande
Tout ce que MaxKB fait en matière d’isolation se déroule dans apps/application/flow/backend/sandbox_shell.py, et dans la v2.10.3-lts, cela commence par une valeur par défaut. La ligne 9 contient _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), et SANDBOX n’apparaît pas dans Config.defaults dans apps/maxkb/conf.py. En l’absence d’un paramètre MAXKB_SANDBOX explicite, la valeur est zéro, la branche wrapper de la ligne 65 est ignorée, et execute atteint subprocess.run avec shell=True directement sur l’hôte, en tant qu’utilisateur exécutant le service — root, selon la formulation de l’avis, si le service s’exécute en tant que root.
Voilà la configuration que les chercheurs ont utilisée pour leur preuve de concept sur l’hôte. Ils ont exécuté le code réel de MaxKB depuis les sources avec MAXKB_SANDBOX non défini, créé un assistant auquel était attaché un seul outil, puis lui ont demandé, dans un unique message de chat, d’exécuter des commandes d’informations système. L’outil execute s’est déclenché et a écrit un fichier dont le contenu était la sortie propre à l’hôte de uname, id et sw_vers — une sortie dont l’avis note qu’elle a été confirmée absente dans tout conteneur. Lasso consigne aussi la limite de ce qui l’a arrêté : un fichier de preuve au nom flagrant a été refusé par le modèle, tandis qu’une formulation opérationnelle anodine ne l’a pas été. L’alignement du modèle, selon eux, est « un ralentisseur partiel, pas un contrôle ».
Sur l’image officielle, le bac à sable s’est exécuté et a tout de même fuité.
Le conteneur officiel définit MAXKB_SANDBOX=1 dans l’image de base, à la ligne 48 de installer/Dockerfile-base, donc le wrapper y est actif — et le wrapper constitue le second défaut. Il construisait une seule chaîne : env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so suivie de gosu sandbox, puis de la commande fournie par le modèle, le tout remis à un shell s’exécutant en root. Parce que la commande était interpolée comme du texte, seul son premier jeton se trouvait sous gosu. Tout point-virgule, pipe, redirection ou substitution de commande dans la sortie du modèle était évalué par le shell root externe avant même que la sandbox ne le voie.
Le compte rendu de Lasso en donne la forme opérationnelle : une charge utile de env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, dans laquelle ls est confiné, whoami ne l'est pas, et tout ce qui suit s'exécute librement. Lors des tests, les chercheurs ont écrit un fichier appartenant à root au moyen d'une redirection alors que la commande interne exécutée dans le bac à sable était bloquée. Pour aggraver les choses, ni installer/Dockerfile ni installer/Dockerfile-base ne contient de directive USER, de sorte que l'image applicative s'exécute avec l'UID 0 — l'avis indique que l'accès root a été confirmé à l'exécution. Le conteneur exécutait donc les commandes malgré tout, et le bac à sable ne décidait que des commandes qui seraient attribuées, de façon cosmétique, à l'utilisateur à faibles privilèges.
Le flux d’attaque complet décrit par Lasso ne nécessite aucun accès à la cible. L’attaquant place des commandes sur une page web, attend que l’agent d’une victime les indexe dans une base de connaissances, puis la victime pose une question ordinaire. La réponse revient correcte et légitime ; le curl injecté a déjà été déclenché sur le serveur de l’attaquant. L’avis précise que les chercheurs n’ont testé que leurs propres déploiements, et non une instance MaxKB tierce ou hébergée.
Ce que les sources établissent, et ce qui n’est tout simplement pas mesuré
Le mécanisme, les deux modes de déploiement, le crédit et la version corrigée concordent dans quatre documents : l’avis GitHub, l’enregistrement NVD publié le 21 septembre 2026, l’analyse technique de Lasso du 10 septembre 2026 et le rapport de GBHackers du 22 septembre 2026, qui est la seule couverture indépendante trouvée pour cette CVE. Aucune source ne conteste une partie quelconque de la conclusion, et l’archive consigne l’entrée comme non contestée à son niveau de confiance le plus élevé.
Ce que les sources ne contiennent pas, c’est une quelconque mesure d’exposition. Il n’y a aucun décompte des déploiements de MaxKB, aucun décompte des assistants exposés à Internet ou intégrés, aucun résultat de scan, aucune télémétrie et aucune victime nommée. Rien dans le dossier ne montre que la faille ait été utilisée contre quiconque, et l’évaluation de l’exploitation de la CISA est du même avis : le bloc SSVC joint à l’enregistrement NVD le 22 septembre 2026 classe l’exploitation comme « poc », l’automatisabilité comme « yes » et l’impact technique comme « total ». Le modèle EPSS de FIRST estimait la probabilité d’exploitation dans les 30 jours à 1,05 pour cent, soit le 64e centile, le 27 octobre 2026, et la CVE n’apparaît pas dans le catalogue Known Exploited Vulnerabilities de la CISA daté du 27 octobre 2026. La note attribuée par l’archive reflète les mêmes éléments de preuve : gravité élevée, préjudice réel faux.
Le 10.0 mérite que l’on précise sa portée, car c’est le chiffre le plus susceptible d’être cité hors contexte. Il s’agit du score pour le cas de l’assistant public ou intégré, où le vecteur CVSS se lit AV:N/AC:L/PR:N/UI:N/S:C — accessible par le réseau, aucun privilège requis, aucune interaction de l’utilisateur, avec un changement de périmètre parce qu’une commande exécutée dans l’assistant franchit la frontière vers le système d’exploitation hôte. Le score est celui du CNA, et le CNA est ici le programme d’avis de GitHub, vers lequel pointe également l’identifiant de source de l’enregistrement CVE. NVD reprend le même vecteur comme métrique secondaire et, au 28 octobre 2026, classe l’entrée au statut « Deferred », ce qui signifie que NVD a publié l’analyse de l’assigneur plutôt que la sienne.

Le correctif a été publié un mois avant l'avis.
La chronologie remonte à rebours depuis la publication, et c'est la partie la moins intuitive du dossier. Lasso a signalé la faille en privé via le canal d'avis de sécurité de GitHub le 8 juillet 2026. MaxKB a répondu le lendemain, en circonscrivant le signalement à l'image officielle et en demandant une preuve de concept sous forme de conteneur ; les chercheurs l'ont fournie, ainsi que le contournement du bac à sable, le 10 juillet. Un commit de correctif, 594f50f2, a été intégré le 9 juillet — un jour après le signalement — et a réécrit sandbox_shell.py de sorte que la chaîne de commande du modèle soit d'abord analysée et que le préfixe gosu soit appliqué à chaque commande simple plutôt qu'à la première seulement, chaque liste d'arguments étant re-échappée afin que la substitution ne puisse pas s'échapper vers le shell parent. Le compte rendu de Lasso décrit ce changement comme appliquant le préfixe gosu « à chaque commande simple, et pas seulement à la première ».
La version qui le contient, v2.10.5-lts, a été publiée le 6 août 2026. L'avis GitHub est paru le 2 septembre, NVD a publié la CVE le 21 septembre, le bloc SSVC de la CISA a été ajouté et GBHackers a rapporté l'information le 22 septembre, tandis que l'article de Lasso lui-même est paru le 10 septembre — au milieu de cette séquence, pas au début. Un opérateur qui suivait les tags de version plutôt que les flux d'avis disposait du correctif environ quatre semaines avant l'alerte.
La limite de version mérite plus d’attention que l’avis ne lui en accorde, car les deux sources principales ne concordent pas et le dépôt tranche la question. Le champ du formulaire de l’avis indique les versions affectées comme « <= 2.10.3-lts », avec une note précisant que cela a été vérifié sur 2.10.3-lts et que le chemin vulnérable « affecte probablement » toutes les versions qui construisent les agents de cette manière. L’analyse publiée par Lasso indique quant à elle une plage affectée de « <= 2.10.4-lts ». Les étiquettes confirment la plage plus large : v2.10.4-lts, publiée le 16 juillet 2026, contient le même sandbox_shell.py de 75 lignes que v2.10.3-lts, et le fichier réécrit de 311 lignes apparaît pour la première fois dans v2.10.5-lts. Un opérateur sous 2.10.4-lts qui n’aurait lu que la plage de l’avis aurait conclu qu’il en était exclu. Il ne l’était pas.

Ce que le correctif n'a pas fait
Ce que corrige la version 2.10.5-lts, c'est l'enveloppe : elle ne construit plus une chaîne shell unique sous root. En revanche, elle ne fait rien concernant l'outil. La lecture directe du dépôt au tag v2.10.8-lts, publié le 22 octobre 2026, montre que l'agent est toujours construit avec backend=SandboxShellBackend et que interrupt_on contient toujours exactement trois clés — write_file, read_file et edit_file — sans execute. Les deux premières suggestions de remédiation de l'avis, à savoir construire sur un backend sans exécution par défaut et ajouter « execute » : True à la table d'approbation, ne sont pas présentes dans cette version.
La recommandation « fail-closed » est arrivée plus tard, dans la v2.10.7-lts, et elle compte pour le mode de déploiement qui était le plus mal loti. Publiée le 15 octobre 2026, elle fait passer la ligne de sandbox_shell.py de CONFIG.get("SANDBOX", 0) à CONFIG.get("SANDBOX", 1). Une installation depuis les sources ou sur machine nue qui n'a jamais défini la variable voit désormais le wrapper activé par défaut plutôt que désactivé, ce qui correspond, au sens étroit, à la recommandation « fail closed on non-container deploys ». L'avis demandait davantage sous le même intitulé — que le flux capable d'exécution refuse de démarrer lorsque le runtime de sandbox est indisponible — et demandait séparément que le wrapper ne construise jamais de chaîne de commande pour un shell root. Côté conteneur, un fait plutôt qu'une recommandation : ni installer/Dockerfile ni installer/Dockerfile-base ne porte de directive USER à l'étiquette v2.10.8-lts, si bien que l'image applicative démarre toujours en root.
Lus ensemble, l’état des lieux au 28 octobre 2026 est le suivant. La seconde moitié de la vulnérabilité — le bac à sable dont un point-virgule s’est échappé — est fermée, et le comportement fail-open par défaut des déploiements sur hôte est fermé. La première moitié, un outil d’exécution qui arrive avec un objet backend et ne figure pas comme clé dans la table d’approbation, reste la manière dont MaxKB construit un assistant doté d’outils. Le conseil de remédiation des chercheurs eux-mêmes était le plus étroit : mettre à niveau vers 2.10.5-lts ou une version ultérieure, et exécuter la version Docker avec le bac à sable activé. GBHackers a relayé la même instruction, ainsi qu’une liste plus large destinée aux administrateurs — désactiver les backends d’agents capables d’exécuter des commandes shell, sauf si l’exécution de code est explicitement requise ; exiger une approbation humaine avant toute action d’exécution ; exécuter les conteneurs en tant que non-root ; et traiter les pages explorées, les documents RAG et les fichiers téléversés comme des entrées non fiables.
L'autre enregistrement MaxKB du même lot de septembre
La deuxième entrée MaxKB de ce lot dans l’archive est un bug différent avec une fin pire. CVE-2026-77516, également publiée sur NVD le 21 septembre 2026, est un contournement de permissions plutôt qu’une injection de commandes : de la version 2.0.0 à la version 2.9.2, un membre d’espace de travail au rôle le plus bas, à qui l’accès à un outil était explicitement refusé via WorkspaceUserResourcePermission, pouvait néanmoins lier l’identifiant de cet outil via tool_ids, skill_tool_ids ou mcp_tool_ids et l’exécuter via le chemin de dispatch de l’agent ou du workflow. Le chemin de dispatch ne réapplique pas l’autorisation par outil que les routes d’outils dédiées imposent, et l’exécution de l’outil déchiffre les init_params côté serveur, de sorte que l’appelant reçoit les identifiants portés par l’outil auquel il s’est vu refuser l’accès. Son score est de 5,4, et la description de NVD se termine par une phrase que CVE-2026-77521 n’a pas à inclure : « Aucune version corrigée n’est disponible au moment de cette revue. »
Le contraste est la partie utile pour quiconque évalue la paire. La faille qui a obtenu un score de 10,0 a bénéficié d’un correctif commité en l’espace d’un jour et publié un mois avant sa publication. La faille qui a obtenu un score de 5,4 n’avait aucune version corrigée publiée au moment de sa CVE.

Ce qui reste réellement ouvert est plus petit que ne le suggère le score et plus grand que ne l'implique une note de correctif. La découverte n'est pas contestée, et le mécanisme a été vérifié de bout en bout sur les deux modes de déploiement par l'équipe qui l'a découvert. L'exposition est entièrement non mesurée — personne n'a publié combien d'assistants MaxKB disposent d'un outil, combien parmi eux sont accessibles à une partie non fiable, ou combien fonctionnent sur un hôte sans le bac à sable —, de sorte que la conséquence réelle de la faille dépend de pratiques de déploiement qu'aucune source citée ne recense. Et la partie de la conception qui a fait monter le score au maximum est toujours présente dans la version actuelle : une capacité qui exécute des commandes, attachée par défaut, absente du tableau qui demande d'abord une validation humaine.
