Illustrazione tecnica astratta su un fondo blu navy scuro: una porta di ingresso luminosa sulla parete sinistra di una scatola traslucida lascia passare una singola linea sottile e pallida che non porta alcun badge né chiave. All'interno della scatola la linea incontra una pila di piccoli pannelli arrotondati e si dirama in una breve fila di tratti angolari simili a comandi che scendono in uno scomparto inferiore contenente un gruppo di gettoni luminosi a forma di chiave. Una seconda porta chiusa, delineata in blu pallido, si trova accanto alla porta di ingresso. Nessun testo, nessuna persona, nessun logo di organizzazione.
AI Safety Incidents

Un'unica POST non autenticata all'API di gestione di Bifrost ha avviato un comando come utente del gateway

Autore

Magnus Corvin

Data di pubblicazione

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

Il 14 settembre 2026, JFrog Security Research ha pubblicato CVE-2026-90898, una vulnerabilità di esecuzione di comandi in Bifrost — il gateway AI open source mantenuto da Maxim — e le ha assegnato un punteggio di 9,8 su 10. L'attacco consisteva in una singola richiesta HTTP. Una POST /api/mcp/client non autenticata registra un client MCP stdio, che Bifrost interpreta come un nome di programma più un elenco di argomenti e avvia immediatamente, prima di qualsiasi handshake MCP, come l'utente che esegue il gateway; nell'immagine ufficiale tale utente è appuser. Un gateway è anche il luogo in cui risiedono le chiavi provider e le chiavi virtuali di un operatore, perciò un processo in esecuzione lì raggiunge le credenziali. Ciò che rendeva anonima la richiesta era una configurazione predefinita inclusa nel prodotto: governance.auth_config.is_enabled è false e, secondo la formulazione di JFrog, «l'autenticazione disattivata significa che ogni chiamante è un amministratore locale». Nessuna fonte citata riporta che la vulnerabilità sia mai stata sfruttata. Le fonti, il livello di gravità e la valutazione di affidabilità del record stesso si trovano in l'archivio degli incidenti AI, insieme alle altre vulnerabilità documentate di gateway AI e MCP dell'ultimo anno.

Bifrost è un singolo servizio che si colloca tra un'applicazione e i modelli linguistici che essa chiama. Il suo repository lo descrive come un gateway open source con licenza Apache-2.0 che "unifica l'accesso a oltre 23 provider ... tramite un'unica API compatibile con OpenAI", con proxy MCP, chiavi virtuali, budget e bilanciamento del carico per provider tra le sue funzionalità, e aveva circa 9.150 stelle GitHub al 28 ottobre 2026. Questa combinazione è l'intera ragione per cui una shell su questo particolare host vale un punteggio critico: il processo che instrada le richieste è anche il processo che custodisce le credenziali per ogni upstream verso cui instrada. The Hacker News, nel riportare la falla il 22 settembre, ha descritto la conseguenza in modo chiaro: poiché il gateway memorizza le chiavi API per ogni provider connesso, l'esecuzione di comandi sul processo del gateway concede all'attaccante l'accesso a tali credenziali.

L'intero attacco è stato un singolo POST

L'avviso di JFrog, pubblicato con riferimento JFSA-2026-001686326, descrive un endpoint che esiste per consentire a un amministratore di aggiungere un server MCP. Un client stdio nella specifica MCP non è un URL; è un comando e i suoi argomenti, che il programma host dovrebbe avviare. Bifrost accetta quella configurazione tramite l'API di gestione e avvia il programma non appena il client viene aggiunto. Nessuna negoziazione delle capacità, nessun controllo dell'identità del server, nessun handshake deve riuscire prima — l'avviso è esplicito sul fatto che non è l'handshake ad avviare il processo.

La proof of concept nell'advisory è un breve corpo JSON inviato a un gateway con l'autenticazione lasciata al valore predefinito. Registra un client il cui comando è /bin/sh e i cui argomenti scrivono un file marker, quindi rilegge il marker. JFrog aggiunge un dettaglio operativo che conta durante la risposta agli incidenti: la richiesta HTTP può andare in timeout mentre Bifrost attende un handshake che non arriva mai, e un timeout nei log non significa che il comando non sia riuscito ad avviarsi. A quel punto il processo è già in esecuzione.

Il record CVE, assegnato da JFrog in qualità di CVE Numbering Authority, associa il difetto a CWE-306, autenticazione mancante per una funzione critica, e a CWE-284, controllo degli accessi inadeguato, e indica i due file che contengono l'handler e il relativo middleware: transports/bifrost-http/handlers/mcp.go e transports/bifrost-http/handlers/middlewares.go. Il modulo interessato è github.com/maximhq/bifrost/transports, su Linux e macOS, per tutte le versioni inferiori alla 2.1.0.

Il valore predefinito che ha reso anonima la richiesta

Niente di tutto ciò sarebbe sfruttabile senza una seconda condizione, e la seconda condizione è il default del prodotto stesso. Il middleware di autenticazione della gestione di Bifrost è controllato da governance.auth_config.is_enabled, che viene distribuito con valore false. Con questa opzione disattivata, il middleware tratta ogni chiamante come un amministratore locale — la sintesi dell'avviso stesso è che, con l'autenticazione disattivata, ogni chiamante è un amministratore locale — quindi il controllo che avrebbe bloccato la richiesta non era mai nel percorso.

La correzione, pull request #6757, è stata integrata nel progetto il 2 settembre 2026, dodici giorni prima della pubblicazione della CVE e sei giorni prima della release che la contiene. La sua descrizione è insolitamente franca riguardo alla natura del problema: la pull request chiude due primitive di accesso non autenticato nella stessa API di registrazione, non una. La prima è il client stdio. La seconda è un client MCP http o sse puntato a un indirizzo di loopback o di rete privata, che la pull request definisce una primitiva SSRF contro servizi interni, «incluso l'endpoint dei metadati cloud 169.254.169.254». Entrambe ora vengono rifiutate con HTTP 403 quando la richiesta raggiunge l'handler senza un controllo reale delle credenziali. Gli amministratori autenticati mantengono entrambe le capacità, e gli operatori possono ancora effettuare il provisioning di client stdio tramite config.json.

Quella seconda primitiva non compare nel testo della CVE. È nella patch, ed è il motivo per cui la correzione è una barriera anziché una rimozione: la funzionalità non è mai stata il bug. Lo era trattare un chiamante non autenticato come amministratore.

Dove l'API di gestione era effettivamente in ascolto

La raggiungibilità è la parte del record che le fonti descrivono nel modo più coerente, e misurano meno. L'avviso di JFrog indica come default del binario standard localhost:8080, il che confina un attaccante all'host stesso. L'avviso dello stesso team per la vulnerabilità correlata afferma che l'immagine Docker ufficiale invece si associa a 0.0.0.0, e The Hacker News lo ripete: l'immagine rende l'API di gestione raggiungibile dall'esterno del container se la porta viene pubblicata. L'avvio rapido nel README di Bifrost stesso esegue "docker run -p 8080:8080 maximhq/bifrost", e l'opzione -p di Docker pubblica una porta del container su ogni interfaccia dell'host a meno che non venga specificato un indirizzo. L'avviso GitHub per la vulnerabilità registra che il percorso segnalato è stato verificato sull'immagine pubblicata maximhq/bifrost:latest, dove una richiesta non autenticata ha avviato /bin/sh e ha scritto un marker come appuser.

Ciò che nessuna fonte fornisce è un numero. Non esiste un conteggio delle istanze Bifrost esposte a Internet, nessun risultato di scansione, nessuna telemetria e nessuna vittima. Il resoconto non riporta alcun danno reale, e questa assenza è un fatto che riguarda il modo in cui la vicenda è stata riportata, non una rassicurazione — la classe di vulnerabilità è pericolosa solo quando coincidono due condizioni, un listener esposto e un valore predefinito lasciato invariato, e nessuno ha pubblicato quanto spesso ciò sia accaduto.

Un endpoint, due difetti, una causa principale

Otto giorni prima dell'avviso MCP, il 6 settembre 2026, lo stesso team di ricerca ha pubblicato CVE-2026-86242, un secondo percorso non autenticato nello stesso processo. Scoperta da Or Peles e valutata 8.1, sfrutta POST /api/plugins: Bifrost accetta un plugin personalizzato abilitato il cui percorso è un URL HTTP, il caricatore di oggetti condivisi tratta un percorso con prefisso http come un download, scrive il corpo in un file .so temporaneo e passa quel file a plugin.Open di Go. Se il caricamento riesce, una funzione Init opzionale viene eseguita immediatamente con la configurazione dell'attaccante, come utente del gateway.

La variante di build decide cosa ottiene un attaccante. Nelle build con linking dinamico documentate dal progetto per i plugin Go personalizzati, ci si aspetta che il caricamento riesca, cosa che l'avviso definisce esecuzione di codice da remoto non autenticata. Nell'immagine Docker pubblicata con linking statico, plugin.Open fallisce con "Dynamic loading not supported", quindi la stessa richiesta degrada a server-side request forgery. Un plugin caricabile deve anche corrispondere alla versione di Go, al sistema operativo, all'architettura e al linking dell'host, il che è un vincolo reale e non una formalità. La correzione è transports/v2.0.0, tramite la pull request #5763, e l'intervallo interessato è tutto ciò che è al di sotto.

Il tranello è l'ordine delle release. La v2.0.0 corregge il percorso del plugin e non corregge il percorso MCP — The Hacker News lo afferma esplicitamente, e l'avviso MCP di JFrog conferma che la v2.0.0 consente ancora la registrazione stdio non autenticata. Un operatore che ha applicato la patch tempestivamente dopo l'avviso del 6 settembre era, su quel punto soltanto, ancora esposto finché transports/v2.1.0 non è stato distribuito l'8 settembre. Entrambi i difetti si riducono alla stessa frase in entrambi gli avvisi e nella pull request dello stesso fornitore: l'autenticazione disabilitata è l'impostazione predefinita.

Ciò che le fonti stabiliscono, e ciò che non stabiliscono

Il meccanismo, l'intervallo di versioni, la correzione e il riconoscimento sono concordati tra l'advisory, il record CVE assegnato da JFrog, la pull request e le note di rilascio del progetto stesso, e The Hacker News. Il disaccordo rimanente riguarda la gravità, ed è reale.

Il 9.8 è il punteggio di JFrog in qualità di CNA assegnatore, ed è il punteggio riportato da NVD: il record NVD elenca reefs@jfrog.com come fonte della metrica e, al 28 ottobre 2026, mostra ancora la voce nello stato "Awaiting Analysis", il che significa che NVD ha pubblicato il vettore dell'assegnatore anziché la propria analisi dello stesso. La valutazione SSVC del coordinatore CISA allegata allo stesso record, con data e ora del 14 settembre 2026, riporta sfruttamento "none", automatizzabile "yes" e impatto tecnico "total". Il modello EPSS di FIRST ha stimato la probabilità di sfruttamento nei successivi 30 giorni al 2,3 per cento al 27 ottobre 2026, nell'83º percentile tra tutte le CVE valutate, e né questa CVE né CVE-2026-86242 compaiono nel catalogo CISA Known Exploited Vulnerabilities datato 27 ottobre 2026.

Di contro, Maxim contesta la valutazione. In una dichiarazione a The Hacker News, Akshay Deo, chief technology officer e co-fondatore dell'azienda, ha affermato che il rischio pratico è inferiore a quanto suggerisce il punteggio critico, perché lo sfruttamento richiede che l'interfaccia di gestione sia raggiungibile da una rete non attendibile e che l'operatore abbia lasciato l'autenticazione non impostata; la distribuzione predefinita e documentata, ha detto, colloca il gateway all'interno di una rete privata. The Hacker News riporta che Maxim considera la vulnerabilità di bassa gravità e sta lavorando con JFrog, che ha assegnato il CVE, alla revisione della valutazione. Tale dichiarazione compare in quell'unica testata; non è stata trovata una seconda pubblicazione che citi la posizione di Maxim, e nessuna revisione era stata pubblicata al 28 ottobre 2026 — il record CVE è stato aggiornato l'ultima volta il 14 settembre e la voce NVD il 18 settembre, entrambi ancora a 9.8.

Due ulteriori lacune meritano di essere nominate anziché attenuate. Gli advisory GitHub del progetto, pubblicati il 23 settembre 2026 e che accreditano il ricercatore di JFrog come segnalatore, riportano ancora 9,8 per la falla MCP e 8,1 per quella del plugin, senza alcun segno della revisione descritta da Maxim. E gli intervalli interessati in tali advisory sono scritti rispetto alle versioni dei moduli Go — inferiori a 1.5.27 e inferiori a 1.6.3 — anziché ai tag di rilascio dei transports usati dagli advisory JFrog, quindi un operatore che confronta un documento con l'altro deve riconciliare due schemi di numerazione prima di decidere se una build è interessata.

Rendered two-column card with the kicker 'BIFROST · CVE-2026-90898' and the title 'What the sources establish — and what they do not', subtitled 'Sources: JFrog JFSA-2026-001686326 (14 September 2026), the CVE record assigned by JFrog, NVD, FIRST EPSS, the CISA KEV catalogue, and the project's pull request 6757 and release tags.' The left column, headed 'ESTABLISHED' in blue, lists eight items: score 9.8 with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H supplied by the CNA; CWE-306 missing authentication with CWE-284 access control; unauthenticated POST /api/mcp/client starting a program as the gateway user; affected below transports 2.1.0 when management auth is disabled, the default; fixed in transports 2.1.0, PR 6757 merged 2 September, released 8 September 2026; CISA SSVC of 14 September 2026 with exploitation none, automatable yes, impact total; EPSS 2.3 percent at the 83rd percentile on 27 October 2026; and not in the CISA KEV catalogue dated 27 October 2026. The right column, headed 'NOT ESTABLISHED, OR CONTESTED' in amber, lists eight items: no exploitation reported, and the archive records real harm as false; no count of exposed or affected deployments in any cited source; severity contested, the vendor's CTO telling The Hacker News it is low; no published revision to the score as of 28 October 2026; NVD still Awaiting Analysis, so the 9.8 is the assigner's and not NVD's; affected ranges stated in two numbering schemes across the advisories; no detection or triage guidance in either advisory; and no evidence tying the flaw to any intrusion. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

Cosa è cambiato e cosa è stato detto agli operatori di fare

La cronologia procede all'indietro rispetto alla divulgazione, che è la parte meno intuitiva del resoconto. La pull request #6757 è stata unita il 2 settembre 2026. transports/v2.1.0, la versione che l'avviso indica come la prima contenente la correzione, è stata pubblicata l'8 settembre — sei giorni prima della pubblicazione di CVE-2026-90898 il 14 settembre. La correzione del plugin del progetto ha preceduto il proprio avviso allo stesso modo: transports/v2.0.0 è stata distribuita il 26 agosto, undici giorni prima del CVE del 6 settembre. Gli operatori che seguono le versioni anziché i feed avevano le patch prima di avere gli avvisi.

Ciò che l'aggiornamento offre è limitato e specifico. Su 2.1.0 e versioni successive, una registrazione stdio non autenticata restituisce 403 e il comando non viene avviato; gli amministratori autenticati mantengono la funzionalità e il provisioning tramite config.json continua a funzionare. La soluzione tampone dell'advisory per chi non può aggiornarsi è impostare governance.auth_config.is_enabled su true, usare credenziali amministrative robuste e tenere il listener di gestione fuori da reti non attendibili. L'istruzione di JFrog per le istanze che hanno operato esposte con l'autenticazione disabilitata non è di indagare e sperare: trattarle come compromesse e ruotare le chiavi virtuali e le credenziali del provider.

La parte più facilmente fraintendibile è l'aritmetica delle versioni. v2.0.0 non corregge questo difetto. Nemmeno la serie 1.6.x fino alla 1.6.11 contiene la correzione, e il tag più recente della serie 1.6 del progetto è transports/v1.6.11, pubblicato il 14 agosto 2026, senza alcuna serie 1.7 nel repository al 28 ottobre 2026 — quindi non esiste una release corretta all'interno di quella serie, e un operatore sulla 1.6.x deve passare alla 2.1.0 o successiva anziché attendere un backport. La linea di rilascio corrente è ben oltre quel punto: transports/v2.3.2 è stato pubblicato il 20 ottobre 2026.

Rendered release-timeline card with the kicker 'BIFROST · RELEASE TIMELINE', the title 'The fix shipped six days before the advisory' and the subtitle 'Dates from the project's release tags and pull request metadata, the JFrog advisories and The Hacker News. Every date below is a single day.' A horizontal timeline carries seven dated markers: 26 Aug 2026, transports 2.0.0 published; 2 Sep 2026, PR 6757 merged; 6 Sep 2026, CVE-2026-86242 published, 8.1; 8 Sep 2026, transports 2.1.0, the fix; 14 Sep 2026, CVE-2026-90898 published, 9.8; 22 Sep 2026, vendor statement reported; 23 Sep 2026, GitHub advisories published. Below it, three bars show release lines: a hatched amber bar labelled '1.6.x line' reading 'affected — no patched release in the series; newest tag 1.6.11, 14 August 2026'; a bar labelled '2.0.0' split between a pale blue segment reading 'plugin flaw fixed' and a red segment reading 'MCP flaw still open'; and a solid blue bar labelled '2.1.0 and later' reading 'MCP fix — unauthenticated stdio registration returns 403'. A foot band headed 'THE PART THAT IS EASY TO GET WRONG' notes that 2.0.0 was the patched release on 6 September and did not close the MCP path, that for the two days before 2.1.0 an operator who patched on the day of the warning was still exposed, and that the 1.6.x series has no fixed release at all. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

Dopo la pubblicazione sono successe due cose di cui un difensore può avvalersi. Gli avvisi di sicurezza GitHub del progetto — GHSA-86gf-xh3g-rvxq per la falla MCP, con severità critica, e GHSA-2qp8-4xgm-fw6g per la falla del plugin, con severità alta — sono stati pubblicati il 23 settembre 2026, fornendo ai feed delle dipendenze e degli avvisi un secondo identificatore su cui fare corrispondenza. E il 13 ottobre 2026 un modello di rilevamento per CVE-2026-90898 è stato unito al repository pubblico nuclei-templates, il che significa che il controllo per un tentativo di registrazione non autenticata ora è qualcosa che una pipeline di scansione può eseguire, invece di qualcosa che ogni team deve scrivere.

Abstract illustration on a dark navy field: a wide translucent slab representing a credential store, filled with evenly spaced glowing key-shaped tokens, stands behind a low wall. A narrow gateway aperture in the wall holds a fresh, brighter set of tokens, a blank card-shaped slip lies pushed aside on the ground in front of it, and a thin amber arc sweeps from the aperture around to the store. A second gateway aperture in the background remains closed and unlit. No text, no people, no organisation logos.

Ciò che resta aperto è la gravità, e sarà risolta o meno dalle due organizzazioni che ne stanno ancora discutendo. La posizione di Maxim, come riportato, è che un 9.8 sovrastima una vulnerabilità che per avere rilevanza richiede un listener esposto e un valore predefinito non impostato — un'affermazione verificabile in linea di principio e non verificata pubblicamente, perché nessuno ha pubblicato quante distribuzioni soddisfacessero quelle due condizioni. La posizione di JFrog è il punteggio che ha assegnato in qualità di CNA, tuttora presente nel record CVE e in NVD. Finché una delle due pubblicherà una revisione, la lettura operativa è la stessa in entrambi i casi: la vulnerabilità è reale ed è stata verificata end to end sull'immagine container pubblicata, la correzione è stata rilasciata prima dell'avviso, la serie 1.6 non ha alcuna correzione, e qualsiasi istanza eseguita con autenticazione disabilitata su un listener raggiungibile dovrebbe essere trattata come un incidente di credenziali anziché come una patch da pianificare.