Illustrazione tecnica astratta su un campo blu navy scuro: un telaio traslucido contiene una pila di piccoli pannelli arrotondati, e un singolo canale scuro senza etichetta scende dal fondo di quella pila direttamente attraverso il pavimento del telaio in un compartimento inferiore non illuminato. Accanto al canale, tre piccoli cancelli pallidi restano chiusi su uno scaffale, mentre il canale stesso passa tra di essi senza alcun cancello sul suo percorso. Una sottile linea ambra entra nel telaio da sinistra e scompare nella pila. Nessun testo, nessuna persona, nessun logo di organizzazione, nessuna raffigurazione letterale di alcun sistema reale.
AI Safety Incidents

MaxKB ha collegato uno strumento shell a ogni assistente abilitato all'uso degli strumenti e non ne ha mai limitato l'accesso

Autore

Alistair Wren

Data di pubblicazione

Ultimi modelli · 20Vedi tutti i modelli →
Benchmark: Artificial Analysis · aggiornato ogni giorno
Torna a tutti gli articoli

MaxKB, una piattaforma assistente enterprise open source pubblicata nell'organizzazione GitHub 1Panel-dev, ha basato i propri agenti di chat su un framework che aggiunge silenziosamente uno strumento shell ogni volta che viene passato un backend in grado di eseguire shell — e MaxKB non ha mai rimosso lo strumento né ha chiesto a qualcuno di approvarne l'uso. La vulnerabilità è CVE-2026-77521, pubblicata come GitHub advisory GHSA-f36j-f34j-h3rx il 2 settembre 2026 e ha ottenuto un punteggio di 10,0 su 10 con CVSS 3.1 nel caso di un assistente pubblico o incorporato. Lasso Security, che l'ha scoperta e segnalata, ha dimostrato che un messaggio di chat — o un testo che l'assistente si limita ad acquisire tramite retrieval o un documento caricato — poteva indurre il modello a eseguire comandi: su un deployment bare-metal direttamente sull'host, e sul container ufficiale tramite un wrapper che, secondo i ricercatori, è aggirabile con un punto e virgola. Nessuna fonte citata riporta che la vulnerabilità sia stata sfruttata in the wild. Il grado di severità, la valutazione della confidenza e l'elenco delle fonti del record stesso si trovano in l'archivio degli incidenti AI, insieme alle voci adiacenti su MaxKB e sugli strumenti per agenti dello stesso lotto di divulgazione.

MaxKB è un prodotto self-hosted per creare assistenti con recupero aumentato: un operatore crea un assistente, vi collega delle capacità — strumenti, server Model Context Protocol, competenze, sotto-applicazioni — connette una base di conoscenza costruita da documenti caricati o da siti web scansionati, e poi espone l'assistente tramite una console autenticata oppure come widget di chat pubblico e incorporabile. Questa versatilità è l'esposizione. La condizione di attivazione dell'avviso non è una configurazione insolita ma quella ordinaria: qualsiasi assistente con almeno una capacità collegata instrada la propria chat attraverso il percorso dell'agente interessato, mentre una chat senza capacità collegate non lo fa. L'analisi di Lasso descrive il progetto come uno dei più ampiamente adottati nella sua categoria e osserva che MaxKB viene normalmente distribuito come servizio multi-tenant — il che colloca un comando eseguito come utente dell'applicazione al di sotto del modello di tenancy anziché all'interno della porzione di un singolo tenant.

Lo strumento shell è arrivato con il framework, non con il prodotto

MaxKB crea questi agenti con la libreria deepagents di LangChain, fissata alla versione 0.6.11 nel pyproject.toml del progetto sia nel tag vulnerabile sia in quello corrente. In apps/application/flow/tools.py, alla riga 467 del tag v2.10.3-lts, il progetto chiama create_deep_agent con backend impostato su SandboxShellBackend, una sottoclasse di MaxKB che esegue comandi sull'host. Secondo l'avviso, deepagents inietta automaticamente un insieme di strumenti ogni volta che viene passato un backend shell in quel modo: execute, ls, read_file, write_file, edit_file, glob e grep. Non fanno parte dell'argomento tools=list, che contiene solo gli strumenti propri dell'operatore, gli strumenti MCP e gli strumenti delle skill. Non possono essere rimossi dall'interfaccia né tramite configurazione.

MaxKB inoltre non passa excluded_tools, l'argomento della libreria che le rimuoverebbe. L'avviso spiega con attenzione perché ciò sia importante anche come rimedio: excluded_tools «rimuove lo strumento da ciò che viene detto al modello, non dall'esecutore». La distinzione tra uno strumento di cui il modello non è a conoscenza e uno strumento che non può essere eseguito è l'intero bug in miniatura.

Un gate che elenca tre strumenti e omette il quarto

Il controllo human-in-the-loop in quella stessa chiamata è una riga, ed enumera tre operazioni: interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. La scrittura di un file, la lettura di un file e la modifica di un file sono nominate. L'esecuzione di comandi non è affatto una chiave nel dizionario. Secondo l'interpretazione dell'advisory, ciò significa che non viene richiesta alcuna approvazione per execute — le tre operazioni del filesystem sono nominate ed esplicitamente impostate per non interrompere, e lo strumento shell non è affatto nominato.

Mettendo insieme i pezzi, il percorso è: testo non attendibile raggiunge il modello, il modello chiama execute e il comando viene eseguito. L'avviso indica due modi in cui può arrivare testo non attendibile. Quello diretto è la chat: un widget pubblico o incorporato, oppure la conversazione di un altro tenant. Quello indiretto è il contenuto che l'assistente acquisisce: un documento RAG, un file caricato o una pagina web che la piattaforma indicizza in una base di conoscenza. Il post di Lasso rende concreta la seconda via, osservando che «l'insieme delle persone che possono mettere testo davanti al modello è più ampio dell'insieme delle persone che possono chattare con esso».

Su un'installazione bare-metal, il comando è solo un comando

Qualunque cosa faccia MaxKB in materia di contenimento avviene in apps/application/flow/backend/sandbox_shell.py e, nella v2.10.3-lts, inizia con un valore predefinito. La riga 9 recita _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), e SANDBOX non compare in Config.defaults in apps/maxkb/conf.py. In assenza di un'impostazione esplicita MAXKB_SANDBOX, il valore è zero, il ramo wrapper alla riga 65 viene saltato e execute raggiunge subprocess.run con shell=True direttamente sull'host, come l'utente che esegue il servizio — root, secondo la formulazione dell'advisory, se il servizio viene eseguito come root.

Questa è la configurazione che i ricercatori hanno usato per il loro proof of concept sull'host. Hanno eseguito il codice reale di MaxKB dai sorgenti con MAXKB_SANDBOX non impostata, creato un assistente con uno strumento collegato e gli hanno chiesto, in un unico messaggio di chat, di eseguire comandi di informazioni di sistema. Lo strumento execute è scattato e ha scritto un file il cui contenuto era l'output di uname, id e sw_vers dell'host stesso — output che, come nota l'avviso, è stato confermato assente all'interno di qualsiasi container. Lasso registra anche il limite di ciò che lo ha fermato: un file di prova con un nome sfacciatamente esplicito è stato rifiutato dal modello, mentre una formulazione operativa benigna non lo è stata. L'allineamento del modello, nelle loro parole, è «un parziale rallentamento, non un controllo».

Sull'immagine ufficiale la sandbox è stata eseguita e presentava comunque una fuga.

Il container ufficiale imposta MAXKB_SANDBOX=1 nell'immagine di base, in installer/Dockerfile-base alla riga 48, quindi il wrapper è attivo lì — e il wrapper è il secondo difetto. Costruiva un'unica stringa: env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so seguita da gosu sandbox e poi dal comando fornito dal modello, passata a una shell in esecuzione come root. Poiché il comando veniva interpolato come testo, solo il suo primo token era sotto gosu. Qualsiasi punto e virgola, pipe, reindirizzamento o sostituzione di comando nell'output del modello veniva valutato dalla shell root esterna prima che la sandbox lo vedesse.

Il resoconto di Lasso ne illustra la forma operativa: un payload di env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, in cui ls è confinato, whoami non lo è, e tutto ciò che segue viene eseguito senza restrizioni. Nei test, i ricercatori hanno scritto un file di proprietà di root tramite un reindirizzamento mentre il comando interno nella sandbox veniva bloccato. A peggiorare la situazione, né installer/Dockerfile né installer/Dockerfile-base contengono una direttiva USER, quindi l'immagine dell'applicazione viene eseguita con UID 0 — l'advisory riporta la conferma di root a runtime. Il container eseguiva quindi comunque i comandi, e la sandbox decideva solo quali di essi venivano attribuiti cosmeticamente all'utente a basso privilegio.

L'intero flusso di attacco descritto da Lasso non richiede alcun accesso al target. L'attaccante inserisce comandi su una pagina web, attende che l'agente di una vittima la acquisisca tramite crawl in una base di conoscenza, e poi la vittima pone una domanda ordinaria. La risposta torna corretta e legittima; il curl iniettato è già stato eseguito verso il server dell'attaccante. L'avviso rileva che i ricercatori hanno testato solo le proprie distribuzioni, non istanze MaxKB di terze parti o ospitate.

Ciò che le fonti stabiliscono e ciò che semplicemente non viene misurato

Il meccanismo, le due modalità di distribuzione, l’attribuzione e la versione corretta concordano in quattro documenti: l’avviso di GitHub, la scheda NVD pubblicata il 21 settembre 2026, la relazione tecnica redatta da Lasso il 10 settembre 2026 e il rapporto di GBHackers del 22 settembre 2026, che è l’unica copertura indipendente trovata per questa CVE. Nessuna fonte contesta alcuna parte della scoperta, e l’archivio registra la voce come non contestata al suo massimo grado di attendibilità.

Le fonti non contengono alcuna misura dell’esposizione. Non c’è alcun conteggio delle distribuzioni di MaxKB, nessun conteggio degli assistenti esposti a Internet o incorporati, nessun risultato di scansione, nessuna telemetria e nessuna vittima nominata. Nulla nella documentazione dimostra che la falla sia stata usata contro qualcuno, e la stessa valutazione dello sfruttamento della CISA concorda: il blocco SSVC allegato al record NVD del 22 settembre 2026 valuta lo sfruttamento come "poc", l’automatizzabilità come "yes" e l’impatto tecnico come "total". Il modello EPSS di FIRST ha stimato la probabilità di sfruttamento nei successivi 30 giorni all’1,05 per cento, il 64º percentile, il 27 ottobre 2026, e la CVE non compare nel catalogo Known Exploited Vulnerabilities della CISA datato 27 ottobre 2026. Il giudizio dell’archivio riflette le stesse prove: gravità alta, danno reale falso.

Il 10.0 merita che se ne espliciti l'ambito, perché è il numero più suscettibile di essere citato fuori contesto. È il punteggio per il caso dell'assistente pubblico o integrato, in cui il vettore CVSS recita AV:N/AC:L/PR:N/UI:N/S:C — raggiungibile via rete, nessun privilegio, nessuna interazione dell'utente, con un cambio di ambito perché un comando all'interno dell'assistente sconfina nel sistema operativo host. Il punteggio è del CNA, e il CNA qui è il programma di advisory di GitHub, che è anche il punto a cui punta l'identificatore di origine del record CVE. NVD riporta lo stesso vettore come metrica secondaria e, al 28 ottobre 2026, elenca la voce nello stato "Deferred", il che significa che NVD ha pubblicato l'analisi dell'assegnatario anziché la propria.

Rendered two-column card with the kicker 'MAXKB · CVE-2026-77521' and the title 'What the sources establish, and what they do not', subtitled with its sources: GHSA-f36j-f34j-h3rx of 2 September 2026, the NVD record of 21 September 2026, Lasso Security's write-up of 10 September 2026, GBHackers of 22 September 2026, FIRST EPSS, the CISA KEV catalogue and the repository tags. The left column, headed 'Established' in blue, lists eight items: CVSS 3.1 base score 10.0 with the vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H for a public or embedded assistant; CWE-78 OS command injection, CWE-250 unnecessary privileges and CWE-749 exposed dangerous method; deepagents 0.6.11 auto-adding execute to any shell backend, with no excluded_tools passed by MaxKB; the approval map covering write_file, read_file and edit_file with execute not a key in it; affected at or below 2.10.3-lts per the advisory and at or below 2.10.4-lts per Lasso Security's write-up; fixed in 2.10.5-lts, published 6 August 2026, 27 days before the advisory; the CISA SSVC assessment of 22 September 2026 with exploitation poc, automatable yes and technical impact total; and EPSS 1.05 percent at the 64th percentile on 27 October 2026 with no listing in the CISA KEV catalogue of that date. The right column, headed 'Not established, or not measured' in amber, lists seven items: no exploitation in the wild recorded by any cited source, with the archive recording real harm as false; no count of affected, exposed or internet-facing deployments; no named victim and no evidence of use in any intrusion; NVD status Deferred, so the 10.0 is the assigner's analysis rather than NVD's; disagreement between the two primary sources on the affected range boundary; the researchers' testing confined to their own deployments; and no detection or triage guidance for either deployment mode. A footer reads 'Card rendered by OrcaRouter. The 10.0 is scored for a public or embedded assistant; the archive grades the record high.' The OrcaRouter logo is composited in the bottom-right corner.

La patch è stata rilasciata un mese prima dell'avviso.

La cronologia procede all'indietro rispetto alla pubblicazione ed è la parte meno intuitiva del resoconto. Lasso ha segnalato la vulnerabilità in privato tramite il canale di advisory di GitHub l'8 luglio 2026. MaxKB ha risposto il giorno successivo, circoscrivendo la segnalazione all'immagine ufficiale e chiedendo una proof of concept in container; i ricercatori l'hanno fornita insieme al bypass della sandbox il 10 luglio. Un commit di correzione, 594f50f2, è stato integrato il 9 luglio — un giorno dopo la segnalazione — e ha riscritto sandbox_shell.py in modo che la stringa di comando del modello venga prima analizzata e il prefisso gosu sia applicato a ogni comando semplice anziché solo al primo, con ogni elenco di argomenti riquotato affinché la sostituzione non possa sfuggire nella shell padre. L'articolo di Lasso descrive la modifica come l'applicazione del prefisso gosu "a ogni comando semplice, non solo al primo".

La release che lo contiene, v2.10.5-lts, è stata pubblicata il 6 agosto 2026. L'advisory di GitHub è stato reso pubblico il 2 settembre, NVD ha pubblicato la CVE il 21 settembre, il blocco SSVC di CISA è stato aggiunto e GBHackers ne ha parlato il 22 settembre, mentre l'analisi di Lasso è apparsa il 10 settembre — nel mezzo di quella sequenza, non all'inizio. Un operatore che seguiva i tag di release anziché i feed degli advisory disponeva della patch circa quattro settimane prima dell'avviso.

Il confine tra le versioni merita più attenzione di quanta ne conceda l'avviso, perché le due fonti primarie sono in disaccordo e il repository risolve la questione. Il campo del modulo dell'avviso registra le versioni interessate come "<= 2.10.3-lts", con una nota secondo cui ciò è stato verificato sulla 2.10.3-lts e che il percorso vulnerabile "probabilmente" riguarda tutte le versioni che compilano gli agent in questo modo. La documentazione di Lasso indica l'intervallo interessato come "<= 2.10.4-lts". I tag confermano l'intervallo più ampio: la v2.10.4-lts, rilasciata il 16 luglio 2026, contiene lo stesso sandbox_shell.py di 75 righe della v2.10.3-lts, e il file riscritto di 311 righe compare per la prima volta nella v2.10.5-lts. Un operatore sulla 2.10.4-lts che avesse letto solo l'intervallo dell'avviso avrebbe concluso di esserne fuori. Non lo era.

Rendered vertical timeline card with the kicker 'MAXKB · CVE-2026-77521' and the title 'Reported, fixed, released, disclosed', subtitled that the dates come from Lasso Security's disclosure timeline, the repository's release tags and commit metadata, the NVD record and GBHackers, and that every date is a single day. Ten dated entries run down a single spine: 8 July 2026, reported privately to 1Panel-dev through GitHub's advisory channel; 9 July 2026, fix commit 594f50f2 rewrites sandbox_shell.py and the vendor asks for a container proof of concept; 10 July 2026, the container proof of concept and the sandbox bypass supplied; 16 July 2026, v2.10.4-lts released, still carrying the 75-line unpatched sandbox_shell.py; 6 August 2026, v2.10.5-lts, the fixed release with a 311-line wrapper and gosu applied to every simple command; 2 September 2026, advisory GHSA-f36j-f34j-h3rx published with CVSS 10.0; 10 September 2026, Lasso Security publishes MaxKBypass; 21 September 2026, NVD publishes CVE-2026-77521, with the CISA SSVC added the next day and GBHackers reporting; 15 October 2026, v2.10.7-lts flips the code default SANDBOX from 0 to 1; 22 October 2026, v2.10.8-lts still builds the agent with SandboxShellBackend and still omits execute. A dark band at the foot headed 'The gap' reads that the fixed release preceded the advisory by 27 days, that v2.10.4-lts was released a week after the fix commit and does not contain the fix, and that the execute tool has never been gated because the approval map at v2.10.8-lts still names only write_file, read_file and edit_file. A footer reads 'Card rendered by OrcaRouter.' The OrcaRouter logo is composited in the bottom-right corner.

Cosa non ha fatto la correzione

Ciò che 2.10.5-lts corregge è il wrapper: non costruisce più un'unica stringa di shell eseguita come root. Quello che invece non fa è intervenire in alcun modo sullo strumento. La lettura diretta del repository al tag v2.10.8-lts, pubblicato il 22 ottobre 2026, mostra che l'agente è ancora costruito con backend=SandboxShellBackend e che interrupt_on contiene ancora esattamente tre chiavi — write_file, read_file ed edit_file — senza execute. I primi due suggerimenti di remediation dell'advisory, ovvero costruire per impostazione predefinita su un backend di non-esecuzione e aggiungere "execute": True alla mappa di approvazione, non sono presenti in quella release.

La raccomandazione fail-closed è arrivata più tardi, nella v2.10.7-lts, ed è importante per la modalità di distribuzione che versava nelle condizioni peggiori. Pubblicata il 15 ottobre 2026, modifica la riga in sandbox_shell.py da CONFIG.get("SANDBOX", 0) a CONFIG.get("SANDBOX", 1). Un'installazione da sorgente o bare-metal che non ha mai impostato la variabile ora ha il wrapper attivato per impostazione predefinita anziché disattivato, il che è la raccomandazione "fail closed on non-container deploys" in senso stretto. L'avviso richiedeva di più sotto la stessa intestazione — che il flusso in grado di eseguire rifiutasse di avviarsi quando il runtime della sandbox non è disponibile — e richiedeva separatamente che il wrapper non costruisse mai una stringa di comando per una shell di root. Sul lato container, un fatto anziché una raccomandazione: né installer/Dockerfile né installer/Dockerfile-base contiene una direttiva USER al tag v2.10.8-lts, quindi l'immagine dell'applicazione si avvia ancora come root.

Letto nel suo insieme, lo stato della situazione al 28 ottobre 2026 è questo. La seconda metà della vulnerabilità — la sandbox da cui è uscito un punto e virgola — è chiusa, e il default fail-open sulle distribuzioni host è chiuso. La prima metà, uno strumento execute che arriva con un oggetto backend e non è una chiave nella mappa di approvazione, è ancora il modo in cui MaxKB costruisce un assistente con strumenti abilitati. Il consiglio di remediation dei ricercatori era quello ristretto: aggiornare a 2.10.5-lts o successivo ed eseguire la versione Docker con la sandbox abilitata. GBHackers ha rilanciato la stessa indicazione, più un elenco più ampio per gli amministratori — disabilitare i backend degli agenti in grado di eseguire shell a meno che l'esecuzione di codice non sia esplicitamente necessaria, richiedere l'approvazione umana prima di qualsiasi azione execute, eseguire i container come non-root e trattare le pagine sottoposte a crawling, i documenti RAG e i caricamenti come input non attendibile.

L'altro record MaxKB dello stesso lotto di settembre

La seconda voce MaxKB dell'archivio relativa a questo lotto è un bug diverso con un finale peggiore. CVE-2026-77516, pubblicata anche su NVD il 21 settembre 2026, è un bypass dei permessi anziché un'iniezione di comandi: dalla versione 2.0.0 alla 2.9.2, un membro del workspace con il ruolo più basso, a cui era esplicitamente negato l'accesso a uno strumento tramite WorkspaceUserResourcePermission, poteva comunque associare l'identificatore di quello strumento tramite tool_ids, skill_tool_ids o mcp_tool_ids ed eseguirlo attraverso il percorso di dispatch dell'agente o del workflow. Il percorso di dispatch non riapplica la concessione per singolo strumento applicata dalle route dedicate agli strumenti, e l'esecuzione dello strumento decrittografa init_params lato server, quindi il chiamante riceve le credenziali trasportate dallo strumento a cui era stato negato l'accesso. Il suo punteggio è 5.4, e la descrizione di NVD si chiude con una frase che CVE-2026-77521 non deve necessariamente riportare: «Nessuna versione corretta è disponibile al momento di questa revisione.»

Il contrasto è la parte utile per chiunque debba fare triage della coppia. La vulnerabilità che ha ottenuto 10.0 aveva una correzione inserita con un commit entro un giorno e rilasciata un mese prima che fosse pubblicata. La vulnerabilità che ha ottenuto 5.4 non aveva alcuna versione corretta pubblicata al momento del suo CVE.

Abstract illustration on a dark navy field: a tall translucent shelf holds a row of small pale gate symbols, and a wide unbroken corridor runs beneath the shelf from left to right with nothing standing in it. At the corridor's midpoint a thin amber line drops down from the shelf above and joins the corridor floor, and a small cluster of glowing key-shaped tokens rests just past the join, out of reach of the gates. No text, no people, no organisation logos, no literal depiction of any real system.

Ciò che resta davvero aperto è più piccolo di quanto il punteggio suggerisca e più grande di quanto implichi una nota di patch. La scoperta non è contestata e il meccanismo è stato verificato end-to-end su entrambe le modalità di deployment dal team che l'ha individuato. L'esposizione è del tutto non quantificata — nessuno ha pubblicato quanti assistenti MaxKB dispongono di uno strumento, quanti di questi siano raggiungibili da una parte non fidata o quanti girino su un host privo della sandbox — quindi la conseguenza reale della vulnerabilità è funzione di abitudini di deployment che nessuna fonte citata quantifica. E la parte del design che ha portato il punteggio al massimo è ancora presente nella versione attuale: una capacità che esegue comandi, allegata per impostazione predefinita, assente dalla mappa che chiede prima l'intervento di un umano.