Sicherheit

Auf dieser Seite

Der Hub führt Skripte aus, die ein Modell geschrieben hat, mit Ihren Rechten, in Ihren Anwendungen. Die Seite sagt, was der Hub begrenzt, welche Risiken bleiben und was Ihren Rechner verlässt, und nennt die dafür wiederholten Messungen. Sie richtet sich an alle, die entscheiden, ob sie ein Modell mit ihren Anwendungen verbinden.

Die Messungen liefen unter Debian 13 mit dem Hub 0.1.0, gebaut aus seinen Quellen; die an einem laufenden Hub nutzten ein Wegwerf-Home-Verzeichnis mit eigenem Token.

Was den Rechner verlässt

Alles, was der Hub zurückgibt, geht an das Sprachmodell und damit an alle, die es ausführen.

WasVerlässt den Rechner
Das Skript, das das Modell geschrieben hatJa: Das Modell ist sein Autor
stdout, stderr und result eines SkriptsJa: Sie können den Inhalt eines Dokuments enthalten
Die FehlerspurJa: Sie enthält Pfade des Rechners
stateJa: Er enthält Inhalte aus den geöffneten Dokumenten
Der Pfad einer AufnahmeJa: er gehört zur Antwort
Das Bild einer AufnahmeNur wenn das Modell die Datei liest
Das Audit-Journal, das Token und die KonfigurationNie

Wer in einer verbundenen Anwendung ein vertrauliches Dokument öffnet, weiß, dass das Modell dessen Inhalt lesen kann. Bei der Wiederholung gab get_state die Bezeichnung Notes einer Ebene zurück, die ein Skript angelegt hatte, mit content_origin auf document; diese Bezeichnung wird so gelesen wie der Inhalt eines Dokuments.

Der Hub verbindet sich nur mit Brücken auf 127.0.0.1. Unter strace -f -e trace=connect,bind,listen durch eine Sitzung hindurch, die ein Skript enthielt, das seine Frist überschritt, machte der Hub insgesamt ein connect über IP: zu 127.0.0.1, auf dem Port der Blender-Brücke. cargo test --locked --test invariants sucht im Quelltext nach jeder weiteren.

Wer eine Brücke erreichen kann

Eine Brücke lauscht nur auf 127.0.0.1, nimmt jeweils eine Verbindung an und antwortet einem Client, der mit dem Token beginnt. ss -ltn zeigte einen lauschenden Socket für die Blender-Brücke, auf dem für den Lauf gesetzten Port: 127.0.0.1:9313. Vier Proben wurden an sie gesendet, bevor sich der Hub verband:

  • Ein hello mit falschem Token: 0 Bytes zurück, und die Verbindung wurde sofort geschlossen.
  • Eine HTTP-Anfrage: 0 Bytes zurück, und die Verbindung wurde sofort geschlossen.
  • Nichts gesendet: 0 Bytes zurück, und die Verbindung wurde nach 5,0 s geschlossen.
  • Ein hello mit dem richtigen Token: 99 Bytes zurück, die hello-Antwort, die die Anwendung und die Versionen nennt und das Token nicht enthält. Die Verbindung blieb offen.

Der eigene UNO-Port von LibreOffice hat keine Authentifizierung. Mit soffice, das auf 127.0.0.1:2102 lauschte, und ohne vorgelegtes Token las ein Python-Client mit python3-uno die LibreOffice-Version 25.2.3.2, öffnete ein Calc-Dokument und schrieb eine Zelle hinein. Dieser Weg umgeht das Token, die Skriptsperre und das Audit-Journal.

Was der Hub begrenzt

Die Grenzen sind Schlüssel des Abschnitts [hub] in config.toml, in der Datei, die init schreibt; die Werte unten sind die Standardwerte, die sie aufführt.

  • Skriptgröße, max_script_bytes, 262 144 Bytes: Ein Skript von 300 009 Bytes wurde mit script is 300009 bytes; the limit is 262144 bytes abgelehnt.
  • Ausgabe pro Strom, max_output_bytes, 1 048 576 Bytes: Ein Skript, das 2 000 000 Zeichen ausgab, lieferte ein stdout von 1 048 576 Bytes und "truncated": true.
  • Zeit, default_timeout_s, 30 s: Im Modus cli kam timeout nach 30,0 s, kein Kindprozess blieb zurück, und der nächste Aufruf war nach 31 ms ok. Im Modus tcp kam timeout nach 31,2 s (32,0 s im zweiten Lauf), dann busy für den nächsten Aufruf.
  • Ein Skript zur Zeit pro Anwendung: das busy oben. Im Modus tcp wurde die Anwendung nicht angehalten; sie führte ihr Skript von 40 Sekunden bis zum Ende aus, und der Hub antwortete 40,3 s nach dem Start wieder mit ok (40,1 s im zweiten Lauf).

Nur der Modus cli beendet ein Skript, das seine Zeit überschreitet. In den Modi tcp und uno kann der Hub ein Skript in der Anwendung nicht unterbrechen: Er antwortet timeout, lehnt neue Skripte mit busy ab und wartet.

Die Skriptsperre

Die Sperre liest den Text eines Skripts, bevor es gesendet wird. Ein Skript, das os.remove aufrief, wurde abgelehnt, bevor es Inkscape erreichte, mit Kategorie, Konstrukt und Zeile: G-1 (file deletion) at line 3: os.remove. Lässt sich ein Pfad aus dem Text nicht prüfen, lässt die Sperre das Skript durch und fügt stderr eine Warnung hinzu, zum Beispiel path not statically verifiable (open()).

Ein Skript, das eine zweite Datei schrieb und mit runpy ausführte, löschte eine Datei, die es selbst angelegt hatte, und der Hub antwortete ok. Das ist die Grenze, die die README des Repositorys nennt: Die Sperre sieht runpy, pickle, http.server, die Speicherfunktionen der Anwendungen und einen Pfad, der einer Funktion als Parameter übergeben wird, nicht. Der Bediener hebt die Sperre mit allow_dangerous_scripts = true im Abschnitt [security] auf; die beiden Werkzeuge kennen keinen solchen Parameter, und das Journal verzeichnet dann guard: bypassed.

Zu den Fehlalarmen der Sperre gab cargo test --locked --test guard realistic -- --nocapture aus: false positives: 0 of 21 realistic scripts (0.0%).

Dateien, Modi und verweigerter Start

Nach init hatten config.toml und token beide den Modus 600. Eine Aufnahme, die get_state angefordert hatte, war eine Datei im Modus 600 in einem Verzeichnis im Modus 700 unter XDG_RUNTIME_DIR; sie war nach dem Ende des Hubs mit Exit-Code 0 noch vorhanden.

Der Hub verweigerte den Start, mit Exit-Code 1 und einer erklärenden Zeile, in fünf Fällen:

FallMeldung, ohne den Pfad
die Token-Datei im Modus 0640has mode 0640; expected 0600 (chmod 600)
keine Token-Dateidoes not exist
config.toml im Modus 0644configuration file refused: … has mode 0644; expected 0600 (chmod 600)
das Laufzeitverzeichnis des Hubs im Modus 0755has mode 0755; expected 0700 (chmod 700)
XDG_RUNTIME_DIR nicht gesetztXDG_RUNTIME_DIR is not set; refusing to write volatile files elsewhere

Der Wert des Tokens erschien in keiner dieser Meldungen. libremodular-launch libreoffice lehnte eine Brückendatei im Modus 0664 ab, bevor es irgendetwas startete, mit Exit-Code 2: has mode 0664 and can be changed by the group or by others (chmod go-w).

Das Audit-Journal

Jeder Aufruf schreibt eine Zeile in audit.jsonl im Zustandsverzeichnis, im Modus 600, auch get_state. Vier Aufrufe (ein Skript, das lief, eines, das die Sperre ablehnte, eines, das einen Fehler auslöste, und eines für eine deaktivierte Anwendung) schrieben vier Zeilen. Eine Zeile enthält das Datum, das Werkzeug, das Ziel, den Status, die Dauer, die Größe und den SHA-256 des Skripts, das Ergebnis der Sperre und die Größe der Ausgabe:

{
  "ts": "2026-10-21T08:56:27.564Z",
  "tool": "execute_script",
  "target_app": "inkscape",
  "status": "refused",
  "duration_ms": 0,
  "script_bytes": 60,
  "script_sha256": "3696b8a4f24f23da34ba239bbb401c56cd78fb53c2bef48ab2f7d668fd1fdbf8",
  "guard": [
    "G-1"
  ],
  "output_bytes": 524
}

Die Datei hält jeden Eintrag in einer Zeile; hier ist er umbrochen, damit er sich lesen lässt.

Eine Markierungszeichenfolge, die in die Skripte gesetzt wurde, fand sich nicht im Journal, ebenso wenig das Token. Der Skripttext wird nur geschrieben, wenn der Bediener audit_script_text = true setzt.

Die Tests des Repositorys

Diese Befehle sind die der CI des Repositorys. Sie liefen außerhalb des Repositorys (CARGO_TARGET_DIR).

BefehlErgebnis
cargo fmt --checkExit-Code 0
cargo clippy --all-targets --locked -- -D warningsExit-Code 0
cargo test --locked328 bestanden, 0 fehlgeschlagen, 3 ignoriert: zwei brauchen ein echtes LibreOffice, einer einen Benutzer, der nicht root ist
cargo test --locked --test invariants36 bestanden
python3 scripts/build_bridges.py --checkExit-Code 0
python3 -m unittest discover -s tests/bridges189 Tests, OK, 6 übersprungen: zwei brauchen root, vier gelten nur unter Windows

Eine Schwachstelle melden Sie wie unter Über das Projekt beschrieben.

WeiterKompatibilität →