WebAssembly
Segurança
Plugins
Sandbox
Multi-tenant

Wasm für Plugins und Sandbox: Code von Drittanbietern sicher ausführen

Wie das funktionsbasierte Sicherheitsmodell von WebAssembly Wasm zur besten Option für Plugin-Systeme und nicht vertrauenswürdige Codeausführung auf allen Plattformen macht.

Jede erfolgreiche Plattform erreicht einen Punkt, an dem sie anderen erlauben muss, Code zu schreiben, der darin ausgeführt wird. Benutzer-Plugins, benutzerdefinierte Enterprise-Client-Funktionen, Partnererweiterungen, über API gesendete Geschäftsregeln. Das Problem ist immer das gleiche: Wie führt man Code, den man nicht geschrieben hat, auf einer Infrastruktur aus, die man kontrolliert, ohne diese Öffnung in eine Schwachstelle zu verwandeln? Herkömmliche Antworten sind teuer, langsam oder fragil. WebAssembly bietet eine andere Antwort – und um zu verstehen, warum, muss man verstehen, was das Problem schwierig macht.

Warum herkömmliche Lösungen nicht skalierbar sind

Der erste Versuch vieler Teams ist eval() oder gleichwertig: die Ausführung der Codezeichenfolge direkt zur Laufzeit. Die Implementierung ist schnell und die Wartung katastrophal. Der Plugin-Code hat Zugriff auf alles, was der Hostprozess hat – Speicher, Netzwerk, Dateisystem. Ein bösartiges oder einfach fehlerhaftes Plugin kann den gesamten Prozess zum Erliegen bringen oder Daten von anderen Mandanten herausfiltern.

Der zweite Versuch ist ein Plugin-Microservice: Jede Erweiterung wird in einem isolierten Container ausgeführt. Aus Sicherheitsgründen funktioniert es, aber die Betriebskosten wachsen linear mit der Anzahl der Plugins. Auf Plattformen mit Hunderten von Erweiterungen ist die Verwaltung eines Containers pro Client nicht möglich. Die Latenz jedes Container-übergreifenden Aufrufs beeinträchtigt auch Vorgänge, die weniger als eine Millisekunde dauern sollten.

Untergeordnete Prozesse mit Linux-Namespaces sind eine weitere Option – leichter als Container, aber mit dem Initialisierungsaufwand und der Komplexität von seccomp und cgroups, um echte Isolation zu gewährleisten. Es erfordert ein Team, das das Kernel-Modell tiefgreifend versteht. Das gemeinsame Problem all dieser Ansätze besteht darin, dass sie Isolation als etwas Externes behandeln: Sie errichten mithilfe von Betriebssystemmechanismen einen Zaun um nicht vertrauenswürdigen Code. Wasm kehrt diese Logik um.

Das Fähigkeitsmodell: standardmäßig Null

Ein WebAssembly-Modul beginnt mit null Funktionen. Im wahrsten Sinne des Wortes keine. Er kann eine Datei nicht öffnen. Es kann keine Netzwerkanfrage gestellt werden. Umgebungsvariablen können nicht gelesen werden. Es kann nicht auf Bytes außerhalb seines eigenen linearen Speichers zugreifen. Wenn das Modul eine dieser Operationen versucht, ohne dass der Host die entsprechende Schnittstelle explizit zur Verfügung gestellt hat, schlägt die Operation fehl – ​​nicht zur Laufzeit mit einer Ausnahme, sondern strukturell, weil die Funktion, die das Modul aufruft, einfach nicht in der Ausführungsumgebung existiert.

Dies wird als fähigkeitsbasierte Sicherheit bezeichnet und unterscheidet sich konzeptionell vom Umgebungsautoritätsmodell, das nativer Code erbt. Wenn Sie eine native Bibliothek laden, wird diese mit vollständigen Prozessberechtigungen ausgeführt. Wenn Sie ein Wasm-Modul laden, startet es ohne jegliche Privilegien und Sie als Host entscheiden, was geliefert werden soll.

Die Sicherheitsschnittstelle befindet sich im Host-Integrationscode. Sie stellen dem Modul genau die Funktionen zur Verfügung, die Sinn machen – Zugriff auf die Figma-Canvas-API, aber nicht auf das Dateisystem; Zugriff auf Shopify-Bestelldaten, jedoch nicht auf Datenbank-Anmeldeinformationen. Das Modul macht alles, was Sie ihm erlaubt haben, und nicht mehr. Die Angriffsfläche wird explizit angegeben, nicht abgeleitet.

Wie echte Plattformen es nutzen

Figma ist das bekannteste Beispiel. Das Plugin-System führt jedes Plugin in einer Wasm-Sandbox aus. Das Plugin erhält Zugriff auf die Canvas-API – es kann Elemente lesen und ändern, Ebenen erstellen und auf Texteigenschaften zugreifen – aber es hat keinen Zugriff auf alles außerhalb dieses Vertrags. Ein Plugin kann keine Betriebssystemdateien lesen oder beliebige Netzwerkaufrufe durchführen. Dies ist keine Nutzungsrichtlinie; Es ist eine technische Unmöglichkeit. Aus diesem Grund können Sie ein Figma-Plugin von einem unbekannten Entwickler mit einiger Sicherheit installieren, dass es Ihre Dateien nicht herausfiltriert.

Shopify hat eine ähnliche Entscheidung getroffen wie Shopify Functions: Benutzerdefinierte Logik für Rabatte, Warenkorbvalidierung und Versandregeln wird von Händlern als Wasm-Module gesendet. Jeder Aufruf empfängt die Anforderungsdaten, führt ihn innerhalb strenger CPU- und Speichergrenzen pro Aufruf aus und gibt das Ergebnis zurück. Ein Händler mit schlecht geschriebenem Code bringt die Plattform nicht zum Absturz und greift nicht auf Daten anderer Händler zu.

Envoy Proxy verwendet dasselbe Modell für benutzerdefinierte Verkehrsfilter. Unternehmen, die Envoy als Proxy betreiben – Beispiele hierfür sind Istio und AWS App Mesh – können Wasm-Filter schreiben, die Anfragen und Antworten während der Übertragung verarbeiten. Der Filter hat Zugriff auf die Header und den Text, jedoch nicht auf den internen Status des Proxys. Erweiterbarkeit ohne Öffnung des Systemkerns. Spiel-Engines kamen über unabhängige Wege zum gleichen Modell: Modding-Systeme, die es Spielern ermöglichen, Inhalte hinzuzufügen, müssen fremden Code ausführen, ohne das Host-Spiel zu gefährden, und Wasm löst dieses Problem mit demselben Funktionsmechanismus.

Die Kosten für diejenigen, die Plugins schreiben

Diese Sicherheit hat ihren Preis. Ein Plugin für eine Wasm-basierte Plattform zu schreiben ist schwieriger als das Schreiben von JavaScript oder Python.

Das erste Problem ist die Toolchain: Für das Kompilieren für Wasm ist ein kompatibler Compiler erforderlich – Rust und C/C++ bieten ausgereifte Unterstützung, Go bietet experimentelle Unterstützung, Python und Ruby kommen mit Einschränkungen. Der zweite Punkt ist der Systemzugriff: Innerhalb der Sandbox gibt es keinen direkten Zugriff auf etwas anderes als das, was der Host bereitgestellt hat. Bibliotheken, die direkte HTTP-Aufrufe durchführen, funktionieren nicht, wenn der Host die entsprechende Schnittstelle nicht zur Verfügung gestellt hat. Dies erzwingt Designdisziplin, was zunächst frustrierend sein kann.

Auf der Plattformseite liegt die Komplexität darin, die für das Modul verfügbare API genau zu definieren. Eine schlecht gestaltete API ist entweder zu restriktiv – Plugins tun nicht, was sie brauchen – oder zu freizügig, was die Sicherheit beeinträchtigt. Bei diesem Auftrag handelt es sich sowohl um Produkt- und Sicherheitsarbeiten als auch um technische Arbeiten.

Wann ist es sinnvoll, in dieses Modell zu investieren?

Die Entscheidung hat ein klares Profil. Dies ist sinnvoll, wenn Sie eine Plattform mit externen Entwicklern aufbauen, deren Codequalität Sie nicht garantieren können. Dies ist sinnvoll, wenn Sie eine Anpassung pro Mandant mit individuellen Ressourcenlimits benötigen – jeder Client hat seine eigene Logik, aber keiner beansprucht die CPU oder den Speicher. Dies ist sinnvoll, wenn Sie Code verteilen, der auf einer Infrastruktur ausgeführt wird, die Sie nicht vollständig kontrollieren.

Es macht keinen Sinn, wenn die Plugins intern sind und Sie dem Team vertrauen, das sie schreibt. Der Overhead der Toolchain und Systemeinschränkungen erzeugen wirklich beispiellose Spannungen, wenn die Bedrohung, die Sie mindern möchten, in Ihrem Modell nicht vorhanden ist. Das Fazit lautet: Die Erweiterbarkeit nach außen, auf ein Publikum, das Sie nicht kontrollieren, ist das, wofür Wasm sorgt.

Lesen Sie auch