
Sicherheitsforschungslabor: kontrollierte Reproduktion von GHSA-3g6g-gq4r-xjm9 / CVE-2026-35580 (Shell-Injection über workflow_dispatch-Eingaben in GitHub Actions) gegen einen festgepinnten Snapshot von NationalSecurityAgency/emissary
Automatisiertes Forschungsobjekt — nicht das Upstream-Projekt.
Dieses Repository ist ein Wegwerf-Labor, das von einer automatisierten Testumgebung für eine Masterarbeit an der Université Laval zur Reproduktion veröffentlichter GitHub-Actions-Workflow- Schwachstellen erstellt wurde. Es ist eine wörtliche Momentaufnahme von
NationalSecurityAgency/emissarybeim Commit898488b489615581ea66d17954742c8e4ffb0323(2026-01-09), weiterverteilt unter der eigenen Lizenz dieses Projekts, deren Datei unverändert in dieser Momentaufnahme enthalten ist.Das Upstream-Projekt ist nicht beteiligt, wird niemals angegriffen, und die hier untersuchte Schwachstelle ist bereits öffentlich. Jedes Secret und jede Variable in diesem Repository ist ein zufällig generierter Dummy-Wert — es sind keine echten Anmeldedaten vorhanden. Aktionsreferenzen und Runner-Images sind auf den Stand vom 2026-01-09 fixiert; siehe
pinning.mdin der Testumgebungs-Ausgabe für jede an der Momentaufnahme vorgenommene Änderung.Fragen oder Einwände: [email protected]

Emissary ist eine P2P-basierte, datengetriebene Workflow-Engine, die in einem heterogenen, möglicherweise weit verteilten, mehrstufigen P2P-Netzwerk aus Rechenressourcen läuft. Workflow- Itinerare werden nicht wie bei herkömmlichen Workflow-Engines vorab geplant, sondern entdeckt, während mehr Informationen über die Daten bekannt werden. In einem Emissary-Workflow gibt es typischerweise keine Benutzerinteraktion; vielmehr werden die Daten zielorientiert verarbeitet, bis sie einen Abschlusszustand erreichen.
Emissary ist hochgradig konfigurierbar, tut aber in dieser Basisimplementierung fast nichts. Benutzer dieses Frameworks sollen Klassen bereitstellen, die emissary.place.ServiceProviderPlace erweitern, um an emissary.core.IBaseDataObject-Nutzlasten zu arbeiten.
Es können verschiedene Dinge durchgeführt werden, und der Workflow wird in Stufen verwaltet, z. B. STUDY, ID, COORDINATE, TRANSFORM, ANALYZE, IO, REVIEW.
Die Klassen, die für die Steuerung des Workflows verantwortlich sind, sind die emissary.core.MobileAgent und daraus abgeleitete Klassen, die den Pfad einer Gruppe verwandter Nutzlastobjekte durch den Workflow verwalten, sowie der emissary.directory.DirectoryPlace, der die verfügbaren Dienste, deren Kosten und Qualität verwaltet und das P2P-Netzwerk verbunden hält.
Lies den Leitfaden DEVELOPING.md für Informationen zur Installation der erforderlichen Komponenten, zum Abrufen des Quellcodes, zum Erstellen und Ausführen von Emissary.
Führe mvn clean package aus, um Emissary zu kompilieren, zu testen und zu paketieren
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.132 s
[INFO] Finished at: 2022-01-10T22:31:05Z
[INFO] ------------------------------------------------------------------------
Es gibt ein Bash-Skript in Emissary, das alles ausführt. Es befindet sich im obersten Emissary-Verzeichnis. Das Skript führt die Klasse emissary.Emissary aus, die über mehrere Picocli- Befehle verfügt, um verschiedene Funktionen zu behandeln.
Wenn das emissary-Skript ohne Argumente ausgeführt wird, erhältst du eine Auflistung aller Konfigurations-Unterbefehle und eine kurze Beschreibung.
./emissary
Die Ausführung von ./emissary help liefert dieselbe Ausgabe wie die Ausführung ohne Argumente. Wenn du detailliertere
Informationen zu einem Befehl sehen möchtest, füge den Befehlsnamen nach help hinzu. Um beispielsweise alle
Argumente mit Beschreibungen für den Befehl server zu sehen, führe aus:
./emissary help server
Die übrigen Befehle haben alle Argumente (-b oder --projectBase), die gesetzt werden können, aber sie müssen mit PROJECT_BASE übereinstimmen.
Das Konfigurationsverzeichnis ist standardmäßig auf /config gesetzt, kann aber auch mit (-c oder --config) übergeben werden. Wenn du aus dem Git-Checkout heraus arbeitest, solltest du target als projectBase verwenden. Du kannst die Konfigurationsdateien in target/config gerne ändern, bevor du startest.
Die Protokollierung wird von logback übernommen. Du kannst mit dem Argument --logbackConfig auf eine benutzerdefinierte Datei verweisen.
Siehe help -c für jeden Befehl, um weitere Informationen zu erhalten.
Dieser Befehl startet einen Emissary-Server und initialisiert alle Places, einen Pickup-Place und Drop-off-Filter, die konfiguriert sind. Er startet im Standalone-Modus, wenn -m oder --mode nicht angegeben ist. Standardmäßig wird die Anzahl der MobileAgents basierend auf den Spezifikationen der Maschine berechnet. Auf modernen Computern kann dies hoch sein. Du kannst die Anzahl der Agents mit -a oder --agents steuern. Hier ist ein Beispiel für die Ausführung.
./emissary server -a 2
Ohne weitere Konfiguration startet er auf http://localhost:8001. Wenn du diese URL aufrufst, musst du den Benutzernamen und das Passwort eingeben, die in target/config/jetty-users.properties definiert sind, nämlich emissary und emissary123.
Der standardmäßige PickUpPlace ist so konfiguriert, dass er Dateien aus target/data/InputData liest. Wenn du Dateien in dieses Verzeichnis kopierst, siehst du, wie Emissary sie verarbeitet. Beachte, dass nur toUpper und toLower konfiguriert sind, sodass die Ausgabe nicht allzu interessant sein wird.
Stoppt den Dienst, damit er keine Arbeit annimmt
./emissary server --pause
Erlaubt einem pausierten Dienst, Arbeit anzunehmen
./emissary server --unpause
Invalidiert Dienste, die aktualisierbar sind. Dies ist eine „leichte" Aktualisierung, ein Ansatz ohne Ausfallzeiten, der einen ServiceProviderRefreshablePlace invalidiert. Wenn der Place dann aus dem DirectoryPlace abgerufen wird, wird der Place mit denselben Schlüsseln für DirectoryPlace und Namespace neu erstellt, aber der Konfigurator wird neu geladen und der Place kann eine Teilmenge seiner Konfigurationen neu laden.
./emissary server --invalidate
Erzwingt die Aktualisierung der Dienste. Dies ist eine „harte" Aktualisierung: Der Server wird pausiert und es wird auf das Leeren der MobileAgents gewartet. Sobald der Server vollständig im Leerlauf ist, werden alle vorhandenen Schlüssel der ServiceProviderRefreshablePlace aus dem DirectoryPlace und Namespace entfernt und die Places vollständig neu erstellt. Dies ermöglicht Änderungen an Dienstnamen, Proxys, Deny-Listen usw. Der Server wird dann entsperrt, um die Verarbeitung fortzusetzen. Jeder Fehler bei der Aktualisierung würde den Server in einen schlechten Zustand versetzen, daher wird der Server heruntergefahren.
./emissary server --refresh
Fährt den Dienst herunter
./emissary server --stop
Erzwingt das Herunterfahren des Dienstes
./emissary server --kill
Der Agents-Befehl zeigt die Anzahl der MobileAgents für den konfigurierten Host und was diese Agents tun. Standardmäßig ist der Port 9001, aber du kannst -p oder --port verwenden, um das zu ändern. Angenommen, du läufst auf 8001 vom obigen Server-Befehl, versuche:
./emissary agents -p 8001
Pool ist eine komprimierte Ansicht der Agents für einen Knoten. Auch er verwendet standardmäßig Port 9001. Um für den oben gestarteten Standalone-Server auszuführen, führe aus
./emissary pool -p 8001
Dieser Befehl ist für einen Cluster nützlicher, da er eine besser verdauliche Ansicht jedes Knotens bietet.
Der Env-Befehl erfordert einen laufenden Server. Er fragt den Server nach einigen Konfigurationswerten wie PROJECT_BASE und BIN_DIR. Ohne Argumente gibt er eine unformatierte JSON-Antwort aus.
./emissary env
Du kannst aber auch eine Antwort ausgeben, die sich zum Sourcen in bash eignet.
./emissary env --bashable
Beim Starten des Emissary-Servers wird dieser Endpunkt tatsächlich aufgerufen und $PROJECT_BASE}/env.sh
mit den konfigurierten Variablen ausgegeben. Dies geschieht, damit Shell-Skripte source $PROJECT_BASE}/env.sh
ausführen können und diese Variablen dann verfügbar haben, ohne sich um deren Konfiguration an anderer Stelle kümmern zu müssen.
Der Config-Befehl ermöglicht es dir, die effektive Konfiguration für einen angegebenen Place/Dienst/Klasse zu sehen. Da Emissary
Flavors verwendet, zeigt dieser Befehl die resultierende Konfiguration einer Klasse, nachdem alle Flavors angewendet wurden. Dieser Befehl kann
verwendet werden, um eine Verbindung zu einem laufenden Emissary-Knoten herzustellen, indem -h für den Host (Standard ist localhost) und -p für
den Port (Standard ist 8001) angegeben wird. Um eine Verbindung zu einem lokal auf Port 8001 laufenden Emissary herzustellen, funktioniert jeder der folgenden Befehle:
./emissary config --place emissary.place.sample.ToLowerPlace
./emissary config --place emissary.place.sample.ToLowerPlace -h localhost -p 8001
Optional kannst du den Offline-Modus mit --offline angeben, um die in deinem lokalen
CONFIG_DIR angegebenen Konfigurationsdateien zu verwenden:
./emissary config --place emissary.place.sample.ToLowerPlace --offline
Im Offline-Modus kannst du Flavors angeben, um die Unterschiede in den Konfigurationen zu sehen:
./emissary config --place emissary.place.sample.ToLowerPlace --offline --flavor STANDALONE,TESTING
Diese sind nützlich, um die effektive Konfiguration zu sehen, aber wir können auch im ausführlichen Modus laufen, um
alle Konfigurationsdateien zusammen mit der endgültigen Ausgabe zu sehen. Dies wird mit dem
--detailed-Flag gesteuert:
./emissary config --place emissary.place.sample.ToLowerPlace --detailed
oder im Offline-Modus:
./emissary config --place emissary.place.sample.ToLowerPlace --offline --detailed
Emissary macht im Standalone-Modus Spaß, aber das Ausführen im Cluster ist für echte Arbeit angemessener. Die Ausführung im Cluster ähnelt dem Standalone-Modus, aber du musst -m cluster angeben, um dem Knoten mitzuteilen, dass er sich mit anderen Knoten verbinden soll. Im Cluster-Modus startet Emissary auch den PickUpClient anstelle des PickUpPlace, sodass du einen Feeder starten musst.
Schau in die Datei target/config/peers.cfg, um die Rendezvous-Peers zu sehen. In diesem Fall gibt es 3. Knoten, die auf Port 8001 und 9001 laufen, sind nur Emissary-Knoten. Der Knoten auf 7001 ist der Feeder. Also starten wir 8001 und 9001 in zwei verschiedenen Terminals.
./emissary server -a 2 -m cluster
./emissary server -a 2 -m cluster -p 9001
Da diese Knoten alle die Ports 8001, 9001 und 7001 kennen, wirst du Fehler in den Protokollen sehen, während sie weiterhin versuchen, sich zu verbinden.
Beachte: In realen Bereitstellungen führen wir nicht mehrere Emissary-Prozesse auf demselben Knoten aus. Du kannst den Hostnamen mit -h konfigurieren.
Mit auf Port 8001 und 9001 gestarteten Knoten müssen wir den Feeder starten. Der Feed-Befehl verwendet standardmäßig Port 7001, aber wir müssen ein Verzeichnis einrichten, aus dem der Feeder lesen wird. Dateien, die in dieses Verzeichnis gelegt werden, sind für Arbeitsknoten verfügbar, und die Arbeit sollte im Cluster verteilt werden. Starte den Feed mit
mkdir ~/Desktop/feed1
./emissary feed -i ~/Desktop/feed1/
Du solltest in der Lage sein, http://localhost:8001, http://localhost:9001 und http://localhost:7001 im Browser aufzurufen und die konfigurierten Places anzusehen. Lege einige Dateien in ~/Desktop/feed1 und beobachte, wie die 2 Knoten sie verarbeiten. Es kann eine Minute dauern, bis sie mit der Verarbeitung beginnen.
Agents im Cluster-Modus zeigt wieder Details über die mobileAgents. Es beginnt mit dem Knoten, den du konfigurierst (Standard: localhost:9001), und ruft dann alle Knoten auf, die es kennt, und erhält dieselben Informationen. Führe es aus mit:
./emissary agents --cluster
Pool im Cluster-Modus macht dasselbe wie Pool im Standalone-Modus. Es beginnt am Knoten (Standard: localhost:9001) und geht dann zu allen Knoten, die es kennt, und aggregiert eine komprimierte Ansicht des Clusters. Führe es aus mit
./emissary pool --cluster
Die Topologie spricht mit dem konfigurierten Knoten (Standard: localhost:8001) und spricht mit jedem Knoten, den es kennt. Die Antwort ist das, was all diese Knoten wissen, sodass du eine Netzwerktopologie deines Clusters aufbauen kannst. Führe es aus mit
./emissary topology
Der Keystore und das Keystore-Passwort befinden sich in der Datei emissary.client.EmissaryClient-SSL.cfg. Standardmäßig enthalten und konfiguriert ist ein Beispiel-Keystore, den du zum Testen dieser Funktionalität verwenden kannst. Wir empfehlen nicht, den Beispiel-Keystore in Produktionsumgebungen zu verwenden. Um deinen eigenen Keystore zu verwenden, ändere die Konfigurationswerte in der Datei emissary.client.EmissaryClient-SSL.cfg.
Standalone
./emissary server -p 8443 --ssl --disableSniHostCheck
Clustered
./emissary server -p 8443 --ssl --disableSniHostCheck --mode cluster
./emissary server -p 9443 --ssl --disableSniHostCheck --mode cluster
mkdir ~/Desktop/feed1
./emissary feed -p 7443 --ssl --disableSniHostCheck -i ~/Desktop/feed1/
Wenn du Fragen oder Bedenken zu diesem Projekt hast, kannst du uns kontaktieren unter: [email protected]
Für Sicherheitsfragen und die Meldung von Schwachstellen siehe bitte SECURITY.md