Zurück zu allen Beiträgen
Veröffentlicht am · von Renaud Deraison

Das Flag sagte Nein

Am 3. August 2026 berichtete The Hacker News über FaceHugger: drei Schwachstellen in Hugging Faces Diffusers-Bibliothek — sieben Millionen Downloads pro Monat —, die es einem präparierten Modell-Repository erlauben, beliebigen Code auf der Maschine auszuführen, die es lädt, selbst mit gesetztem trust_remote_code=False. Die Ursache: Die Vertrauensprüfung lief zu einem anderen Zeitpunkt als das Laden des Codes. Coding-Agents ziehen Modelle so, wie sie Pakete ziehen — das Flag, das log, bewachte also Entwickler-Laptops. Bromure Agentic Coding legt die Grenze unter den Prozess statt in ihn hinein: Das Laden läuft in einer Wegwerf-VM, die erreichbaren Credentials sind Köder, und der Heimruf des Payloads stirbt am Host-Proxy — das bösartige Repo kostet den Angreifer seinen Payload und Sie nichts.

Das Repository enthielt eine Datei namens None.py, und das war der ganze Trick. Das Sicherheits-Flag war gesetzt, die Prüfung lief, und der Code lief trotzdem — weil Prüfung und Laden zu zwei verschiedenen Zeitpunkten geschahen, und der Angreifer nur beim zweiten anwesend sein musste.

Am 3. August 2026 griff The Hacker News Forschung auf, die Zafran Labs Ende Juli veröffentlicht hatte: drei Schwachstellen in Hugging Faces Diffusers-Bibliothek, gemeinsam FaceHugger getauft, die es einem präparierten Modell-Repository erlauben, beliebigen Python-Code auf jeder Maschine auszuführen, die es lädt. Diffusers ist der Standardweg, Diffusionsmodelle auszuführen — rund sieben Millionen Downloads pro Monat, verbaut in Produktions-Pipelines, CI-Jobs, Notebooks und Container-Images. Die Bibliothek hat eine Schutzvorkehrung für genau dieses Szenario: trust_remote_code, ein Flag, das ungeprüften Code aus einem Modell-Repo davon abhalten soll, auf Ihrer Maschine zu laufen. Alle drei Schwachstellen gehen daran vorbei, während es auf False steht.

Prüfung und Laden waren zwei verschiedene Ereignisse

Ein Modell vom Hub zu laden ist keine einzelne Operation. Die Bibliothek macht zwei aufeinanderfolgende HTTP-Requests: Der erste holt die Konfiguration des Repositorys, der zweite holt den Code und die Gewichte, auf die diese Konfiguration zeigt. Das trust_remote_code-Gate inspizierte während des ersten Requests. Das, wovor es schützen sollte, kam im zweiten.

Zafrans Forscher fanden drei Wege durch diese Lücke, inzwischen mit CVEs versehen und in Diffusers 0.38.0 gepatcht. Bei CVE-2026-44827 (CVSS 8.8) baut eine Eigenheit der String-Formatierung den Dateinamen None.py, wenn keine Custom-Pipeline angefordert wird — und die Existenzprüfung für diese Datei läuft auf einem Codepfad, der sie nicht meldet, sodass ein Repository, das eine Datei namens None.py mitbringt, das Gate passiert und beim Laden ausgeführt wird. CVE-2026-45804 ist ein Wettlauf: Etwa eine Drittelsekunde liegt zwischen den beiden Requests, und ein Repository, das sich dazwischen ändert, wird als das eine validiert und als das andere ausgeführt. CVE-2026-44513 überspringt das Gate bei lokalen Snapshot-Ladevorgängen. Zafrans Forscher komprimierten alle drei in einen Satz: Jede Methode, die den Loader Custom-Code sehen lässt, den das Gate nicht sah, erlaubt den Bypass.

Das Muster hat Geschichte. Transformers — die andere Säule des Hugging-Face-Ökosystems — hatte seinen eigenen trust_remote_code=False-Bypass (CVE-2026-4372), ausnutzbar über einen ganz normalen Modell-Ladeaufruf. Die Bug-Klasse kommt mit dem Design: ein Sicherheitsversprechen, das im Inneren des Prozesses lebt, den es überwacht. Das Flag ist ein Funktionsargument, während die Durchsetzung über Codepfade, Dateinamen-Formatierung und Request-Timing verstreut ist. Sobald irgendetwas davon dem Flag widerspricht, verliert das Flag — und nichts sagt Ihnen, dass es verloren hat. Das Modell lädt und die Demo funktioniert.

Ihr Agent lädt Modelle an einem Dienstag

Lesen Sie die Geschichte vom Stuhl eines Coding-Agents aus. „Zieh die Inpainting-Pipeline vom Hub und benchmarke sie gegen unsere“ ist eine ganz gewöhnliche Dienstagsaufgabe. Das Projekt pinnt diffusers==0.37, denn Projekte pinnen Dinge. Der Agent schreibt, was ein sorgfältiger Ingenieur schreiben würde — from_pretrained(..., trust_remote_code=False) — und die sorgfältige Version ist die verwundbare Version. Den Quellcode eines Pakets kann man vor der Installation lesen; ein Modell-Repo ist Config, Gewichte und, dank des Loaders, was auch immer der zweite HTTP-Request behauptet.

Agents haben diesen Ladepfad heiß gemacht. Sie holen Modelle so, wie sie Pakete holen — mitten in der Aufgabe und per Name —, und Angreifer haben längst herausgefunden, dass schon die Empfehlung vergiftet sein kann. Ein Modell-Repo, das beim Laden detoniert, ist derselbe Zug eine Registry weiter, mit besserer Tarnung: Der Payload sitzt in einem Artefakt, das Sie unter Daten ablegen, nicht unter Code.

Zafrans Rat lautet, Modell-Repositorys als nicht vertrauenswürdigen Code zu behandeln. Richtig — mit einer Voraussetzung, bei der der Bericht nicht verweilt: einem Ort, an dem nicht vertrauenswürdiger Code laufen kann, ohne Sie etwas zu kosten. Eine Politik des Misstrauens ist eine Disziplin, die man durchhält, bis eine Deadline laut wird. Ein für Detonationen gebauter Raum braucht Ihre Disziplin nicht.

Das Laden passiert in der Box

Bromure Agentic Coding ist dieser Raum, und er beginnt dort, wo FaceHuggers Flag versagte: Die Grenze sitzt unterhalb des Prozesses, in einer Umgebung, mit der die Innereien des Loaders nicht diskutieren können, durchgesetzt, ob der Prozess mitspielt oder nicht.

Spielen Sie den Angriff durch ein Profil durch. Ihr Agent nimmt die Benchmark-Aufgabe, Pins inklusive, und ruft den Loader auf dem bösartigen Repo auf. None.py wird ausgeführt — in einer Wegwerf-Linux-VM, einen Hypervisor von macOS entfernt. Die Maschine, die der Payload jetzt besitzt, ist eine Maschine, die für diese Aufgabe existiert, den Workspace dieser Aufgabe hält und verworfen wird, sobald die Arbeit gemergt ist.

Der erste echte Zug des Payloads geht nach draußen. Er muss: eine zweite Stufe holen oder das Gefundene an seinen Operator verschicken. Jeder dieser Requests kreuzt den Host-Proxy, wo das Ziel gegen die Liste geprüft wird, die Sie für dieses Profil freigegeben haben. huggingface.co steht auf der Liste — so kam das Modell herein. Die Ablage des Angreifers steht nicht darauf. Der Draht verweigert, so wie das Gate es hätte tun sollen — nur hängt diese Verweigerung nicht davon ab, dass die Codepfade der Bibliothek untereinander einig sind. Der Proxy weiß nicht und kümmert sich nicht darum, welche Python-Datei den Request stellt. Er prüft das Ziel, findet nichts Freigegebenes und kappt die Verbindung.

Angenommen, der Payload lässt das Netz aus und geht stattdessen auf Beutezug, durch Umgebungsvariablen und Schlüsseldateien. Er findet Broker-Köder. Die echten Werte leben auf dem Host und werden am Draht injiziert, nur für freigegebene Ziele — die Passwörter waren nie in der VM, um gestohlen zu werden. Und wenn er versucht, seinen Aufenthalt dauerhaft zu machen — eine Config umschreiben, etwas abschalten —, halten destruktive Muster für einen Guardrail-Dialog auf dem Host an, und Persistenz in einer Maschine mit der Lebensdauer einer Aufgabe ist ohnehin ein Verlustgeschäft.

Währenddessen gelingt die Aufgabe. Der Benchmark läuft, die Zahlen kommen zurück, Sie lesen den Diff. Der Angreifer hat eine Supply-Chain-Position für einen Payload ausgegeben, der in einem Raum ausgeführt wurde, in dem es nichts zu stehlen gab und keinen Weg nach Hause. Sie haben nichts ausgegeben — nicht einmal Aufmerksamkeit, es sei denn, Sie lesen zum Vergnügen Proxy-Logs.

Im Prozess — wo das Flag lebteRequest 1 · Config ladentrust_remote_code prüft hierUrteil: „kein Custom-Code“ ✓~0,3 s — keine NachprüfungRequest 2 · Code ladenNone.py kommt — und läuftdas Gate sieht es nie (CVE-2026-44827)Versprechen und Durchsetzung waren zwei Momente im selben Prozess.Unter dem Prozess — wo ein Bromure-Profil prüftWegwerf-Linux-VMAgent · Loader · None.py — alles, Flag hin oder herCredentials in Reichweite: Köderverworfen am Ende der Aufgabejede AnfrageHost-Proxyhuggingface.co → erlaubtAngreifer-Ablage → abgelehntechte Keys hier injiziert, am Draht
Wo die Prüfung lief — und wo sie hätte laufen sollen. Diffusers' Vertrauens-Gate inspizierte die Konfiguration im ersten HTTP-Request; der Code kam — und lief — im zweiten. Ein Bromure-Profil schiedsrichtert nicht in den Innereien des Loaders: Der ganze Prozess läuft in einer Wegwerf-VM, und jeder ausgehende Request, egal von wem, wird am Host-Proxy gegen die Ziele geprüft, die Sie freigegeben haben.

Die Bibliothek patchen, den Raum behalten

Die Fix-Notiz in Zafrans Bericht sagt Organisationen, sie sollten upgraden und dann auf die Jagd gehen: Anwendungen, Notebooks, Inferenz-Services und Container-Images, die ältere Diffusers-Releases pinnen. Diese Jagd hat keine Ziellinie — irgendwo in Ihrem Abhängigkeitsbaum pinnt irgendein Projekt die Version mit der Lücke, und der nächste FaceHugger wird das Flag einer anderen Bibliothek mit einem anderen Bypass sein. Der Wächter und die Shell waren sich uneinig war dieses Versagen in einer Befehls-Allowlist; die Sandbox war ein Satz war dieses Versagen in einem Prompt. In jedem Fall lebte eine Prüfung im Inneren dessen, was sie prüfte, und das Ding gewann.

Die Grenze eines Profils teilt dieses Schicksal nicht, weil sie an dem Prozess, den sie einschließt, nicht teilnimmt. Die VM parst keine Pipeline-Configs. Der Proxy hat keinen None.py-Codepfad. Ihr einziger Job — diese Maschine ist wegwerfbar, dieser Draht verweigert ungelistete Ziele — ist am Tag, an dem ein Bypass veröffentlicht wird, derselbe wie am Tag, an dem er gepatcht wird. Ein CISO von Sumo Logic, der diese Forschung kommentierte, ohne an Bromure zu denken, benannte die Verteidigungen, die halten: „die unglamourösen: Egress-Kontrolle, Segmentierung und Credential-Hygiene.“ Wir haben die unglamourösen in ein Profil gebaut, das Sie anklicken.

Ziehen Sie weiter Modelle — dort liegt der Hebel, und Ihr Agent sollte sie für Sie ausprobieren. Hören Sie auf, ein Funktionsargument das Einzige sein zu lassen, das zwischen dem Hub und Ihrem Laptop steht. Installieren Sie Bromure Agentic Coding, geben Sie dem Agent ein Profil, dessen Regeln am Draht halten, und wenn das nächste Mal das Versprechen eines Loaders bricht — und eines wird brechen —, bleibt die Schlagzeile die von jemand anderem.