Entwicklung & Code
Werkzeugwahl, Teil 1: Wenn Agenten schreiben, verlieren Sprachen an Bedeutung
Ende September hat David Heinemeier Hansson auf der Rails World eine Keynote gehalten, über die die Ruby-Community noch lange sprechen wird. Ausgerechnet der Erfinder von Ruby on Rails verkündete, dass das Backend der nächsten Version seines E-Mail-Dienstes HEY nicht mehr auf Ruby basiert, sondern auf Rust. Geschrieben hat er es nicht selbst, sondern mithilfe von Coding-Agenten.
Weiterlesen nach der Anzeige
Rust sei zwar eine ästhetisch schreckliche Sprache, aber das sei egal: Er schaue sich den Code ohnehin nicht mehr an. Die schönste Programmiersprache der Welt sei nämlich nicht Ruby, sondern Englisch. Im Saal saßen rund tausend Entwicklerinnen und Entwickler, und es wurde still.
Meine erste Reaktion fiel anders aus: Er hat nicht unrecht. HEY ist keine Raketenwissenschaft, sondern eine Anwendung, deren Code technisch überschaubar ist, und genau solchen Code können Agenten heute ziemlich gut erzeugen. Warum ich der These im Kern zustimme, was sie über die Wahl von Programmiersprachen verrät und wo sie aufhört zu gelten, darum geht es in diesem ersten Teil einer zweiteiligen Serie über die Werkzeugwahl.
Ein Gütekriterium verliert seinen Adressaten
Wie weit dieser Schritt reicht, zeigt ein Blick in die Rails-Doktrin, die Hansson selbst verfasst hat. Ihr erster Grundsatz lautet „Optimize for programmer happiness“ und er beschreibt die ursprüngliche Ketzerei von Ruby: das Wohlbefinden derjenigen, die programmieren, auf ein Podest zu stellen. Ruby sollte sich gut anfühlen, Rails sollte Freude machen, und für sehr viele Entwicklerinnen und Entwickler hat genau das jahrelang funktioniert.

Golo Roden ist Gründer und CTO von the native web GmbH. Er beschäftigt sich mit der Konzeption und Entwicklung von Web- und Cloud-Anwendungen sowie -APIs, mit einem Schwerpunkt auf Event-getriebenen und Service-basierten verteilten Architekturen. Sein Leitsatz lautet, dass Softwareentwicklung kein Selbstzweck ist, sondern immer einer zugrundeliegenden Fachlichkeit folgen muss.
Dieses Kriterium ist keine Eigenheit der Ruby-Welt, es steckt in fast jeder Diskussion über Programmiersprachen. Wer zwischen zwei Sprachen wählt, fragt fast immer auch, wie es sich anfühlt, darin zu arbeiten: wie elegant die Syntax ist, wie viel unnötiges Drumherum nötig ist, wie schnell aus einer Idee lauffähiger Code wird, und so weiter. All das sind Eigenschaften des Schreibens – und sie richten sich an den Menschen, der schreibt.
Schreibt jedoch nicht mehr der Mensch, verliert das Kriterium seinen Adressaten. Einem Agenten ist es nämlich gleichgültig, ob eine Syntax elegant ist: Er empfindet weder Freude noch Verdruss. Deshalb sehe ich in Hanssons Entscheidung keinen Bruch mit seiner eigenen Doktrin, sondern ihre konsequente Fortsetzung. Wenn das Glück beim Schreiben keine Rolle mehr spielt, darf es auch die Wahl der Sprache nicht mehr bestimmen.
Weiterlesen nach der Anzeige
Was übrig bleibt, sind die Eigenschaften des Ergebnisses. Bei Rust sind das vor allem die Garantien des Typsystems, die Performance und der geringe Ressourcenverbrauch. Laut Hansson lässt sich die Zahl der Server für das HEY-Backend auf zehn reduzieren, und selbst das nur wegen der Ausfallsicherheit. Nach seiner Bauchgefühl-Rechnung würde sogar ein einzelner Raspberry Pi genügen. Ob das im Detail stimmt, sei dahingestellt. Die Richtung ist aber eindeutig – und sie hat herzlich wenig mit Ästhetik zu tun.
Für Agenten ist die Sprache fast egal
Naheliegend wäre nun der Schluss, Rust sei eben eine Sprache, die sich besonders gut von KI schreiben lässt. Ich halte diesen Schluss jedoch für falsch, und zwar aus eigener Erfahrung. Richtig ist, dass eine Sprache mit wenig Freiraum etwas hilft: Je weniger Wege es gibt, dasselbe auszudrücken, desto geringer ist die Varianz in den Trainingsdaten und desto gleichförmiger der erzeugte Code. Mit Go habe ich in dieser Hinsicht sehr gute Erfahrungen gemacht.
Überbewertet ist der Effekt trotzdem. Auch mit JavaScript und TypeScript, die deutlich mehr Freiheit lassen, entstehen KI-gestützt sehr gute Ergebnisse, sofern das Projekt mit passenden Leitplanken arbeitet, also mit einem Linter, mit einem Formatter und vor allem mit Tests. Schwierig wird es erst bei wirklich exotischen Sprachen, aber auch dort nicht wegen der Sprache an sich, sondern weil es schlicht zu wenig Trainingsmaterial gibt.
Daraus folgt eine kleine, aber wichtige Verschiebung. Rust liefert bei HEY nicht deshalb bessere Ergebnisse, weil ein Agent Rust besser schreibt als Ruby. Es liefert sie, weil Rust Stärken hat, bei denen Ruby im Hintertreffen ist, und weil diese Stärken plötzlich nichts mehr kosten. Früher zahlte jemand den Preis dafür, sich mit einer strengen und mitunter umständlichen Sprache auseinanderzusetzen. Diesen Preis zahlt nun jedoch der Agent und dem Agenten ist das egal.
Warum ich meine Meinung geändert habe
An dieser Stelle muss ich etwas Persönliches einschieben: Im Mai habe ich hier das Lesen von Code als unterschätzte Senior-Disziplin beschrieben, ausgehend von Joel Spolskys Warnung davor, Code lieber neu zu schreiben, statt ihn zu verstehen. Damals habe ich argumentiert, dass LLMs dieses Problem verschärfen würden. Heute sehe ich das in wesentlichen Teilen anders, und ich halte es für wichtig, das ehrlich anzusprechen.
Code wird nach wie vor deutlich öfter gelesen als geschrieben, etwa wenn ein Feature hinzukommt, wenn ein Fehler behoben werden muss oder jemand verstehen will, was ein Modul macht. Nur liest ihn eben zunehmend ein Agent und immer seltener ein Mensch. Dazu kommt ein schlichtes Mengenproblem. Ein Agent erzeugt Code schneller, als ein Team ihn prüfen kann, und mehr Reviewerinnen und Reviewer ändern daran nichts Wesentliches. Wer jede generierte Zeile von Hand durchsehen will, hat den Engpass nicht beseitigt, sondern nur verschoben und wird dennoch scheitern.
Hier setzt Spec-Driven Development (SDD) an. Gemeint ist ein Vorgehen, bei dem zuerst das gewünschte Verhalten beschrieben wird und ein Agent den passenden Code dazu erzeugt. Geprüft wird dann nicht mehr in erster Linie der Code, sondern ob das Verhalten stimmt. Ausführlicher beschreibe ich diesen Gedanken in „Code ist ein Implementierungsdetail“, der vierten Ausgabe von the native papers.
Der eigentliche Schlüssel ist für mich dabei allerdings nicht die Spezifikation, sondern es sind die Tests, die aus der Spezifikation folgen. Eine Spezifikation in Prosa ist so mehrdeutig wie jede Prosa, und ein Agent legt sie im Zweifel so aus, wie es ihm gerade passt. Ein Test dagegen lässt sich deterministisch ausführen und liefert bei jedem Lauf dieselbe Antwort: Entweder er ist grün oder eben nicht. Natürlich ist ein Test kein mathematischer Beweis und keine echte Garantie im eigentlichen Sinne, er prüft nur stichprobenartig, was er eben prüft. Aber er ist nichtsdestotrotz etwas, das sich objektiv überprüfen lässt, und das ist ungleich mehr als ein Agent, der einfach vor sich hin generiert.
Knapp 1500 Tests, anderthalb Stunden
Wie weit das trägt, habe ich vor einigen Wochen sehr eindrücklich erlebt. Es ging um die Implementierung eines Learning-Record-Stores für xAPI. Die Experience API, kurz xAPI, ist ein Standard für die Erfassung von Lernaktivitäten: Lernplattformen, Simulationen oder Apps melden darüber, wer was gelernt oder geübt hat. Ein Learning-Record-Store nimmt diese Meldungen über eine HTTP-Schnittstelle entgegen, speichert sie und stellt sie für Abfragen bereit.
Das Besondere an diesem Fall war nicht der Standard, sondern die offizielle Testsuite der ADL Initiative, die xAPI verantwortet. Sie prüft die verbindlichen Anforderungen der Spezifikation von außen gegen die HTTP-Schnittstelle, und für xAPI 2.0 umfasst sie 1435 Tests. Eine vollständigere Beschreibung des gewünschten Verhaltens ist kaum denkbar (außer noch mehr Tests zu haben).
Die Anweisung an den Agenten fiel entsprechend knapp aus: „Implementiere das in Go, und iteriere so lange, bis alle Tests grün sind.“
Der Agent brauchte rund 75 Minuten und drehte dabei etliche Schleifen. Runde um Runde schlugen Tests fehl, er besserte nach und nahm den nächsten Anlauf. Am Ende waren alle 1435 Tests grün, und die Implementierung funktioniert nun seit Wochen absolut tadellos.
Die Erkenntnis daraus hat mich mehr beschäftigt als das Ergebnis selbst. Der Erfolg lag weder am Modell noch an der Programmiersprache. Er lag daran, dass es eine gute, umfangreiche und vor allem vollständige Testsuite gab, an der sich jeder Zwischenstand messen ließ.
Ohne sie hätte derselbe Agent mit demselben Modell in derselben Sprache etwas abgeliefert, das plausibel aussieht, und niemand hätte gewusst, an wie vielen Stellen es falsch ist. Wenn Entwicklerinnen und Entwickler abschätzen wollen, wie viel sie einem Agenten überlassen können, lohnt deshalb zuerst ein Blick auf die Tests und erst danach auf die Sprache.
Ein Agent sagt nie, dass er etwas nicht kann
So überzeugend dieses Beispiel ist, so wichtig ist es, seine Grenzen nicht zu verschweigen. Es gibt Dinge, die sich nicht oder nur schlecht testen lassen, und zwar immer dann, wenn sie von Faktoren abhängen, die ein Test nicht oder nicht vollständig kontrollieren kann. Dazu gehört alles, was zwischen mehreren Maschinen passiert, alles, was an Hardware hängt, und auch alles, was vom Threading des Betriebssystems oder vom Verhalten des Netzwerkstacks abhängt. Ein Fehler, der nur bei einer bestimmten zeitlichen Abfolge auftritt, zeigt sich im Test vielleicht einmal in tausend Läufen, vielleicht auch nie – und trotzdem ist er da.
Schwierig wird es außerdem dort, wo es wenig Trainingsmaterial gibt, selbst wenn sich alles vollständig in Software abspielt. In solchen Bereichen findet ein Agent wenig, woran er sich orientieren kann, und zugleich gibt es wenig, was ihn korrigiert.
Das eigentliche Problem ist dabei nicht, dass der Agent scheitert, sondern wie er scheitert. Ein Agent wird nämlich nie sagen, dass er etwas nicht kann. Er meldet stattdessen zu früh, dass er fertig ist, und liefert eine Lösung, die überzeugend aussieht. Ob sie richtig ist, steht auf einem anderen Blatt, und gerade in den schwer testbaren Bereichen ist sie es meiner Erfahrung nach meistens eher nicht.
Damit wird deutlich, welche Rolle Tests in dieser Arbeitsweise tatsächlich spielen: Sie sind die Instanz, die dem Agenten widerspricht. Wo sie stark sind, wie bei der xAPI-Schnittstelle, lässt sich einem Agenten sehr viel überlassen. Wo sie schwach sind, widerspricht ihm niemand mehr, und genau dort wird es gefährlich.
Der Compiler als zweite Instanz
An dieser Stelle schließt sich der Kreis zu Rust und hier liegt für mich das stärkste Argument für Hanssons Entscheidung. Gerade bei Nebenläufigkeit, also dort, wo Tests tendenziell eher schwach sind, verlagert Rust einen Teil der Fehlersuche von der Laufzeit in den Compiler. Das Ownership-Modell sorgt nämlich dafür, dass mehrere Codestellen nicht gleichzeitig veränderlich auf denselben Speicher zugreifen können. Deshalb garantiert Rust, solange der Code ohne ausdrücklich als unsafe markierte Abschnitte auskommt, die Abwesenheit von Data-Races, also von nicht synchronisierten, gleichzeitigen Zugriffen mehrerer Threads, bei denen mindestens einer schreibt.
Hier ist Genauigkeit wichtig, weil dieser Punkt oft übertrieben wird. Rust verhindert nicht jede Art von Race-Condition, und auch Deadlocks schließt es nicht aus; die Dokumentation sagt ausdrücklich, dass das in einer Umgebung, deren Scheduler das Programm nicht kontrolliert, mathematisch unmöglich ist. Aber eine ganze Klasse besonders tückischer Fehler kommt dennoch gar nicht erst durch den Compiler, und das hilft enorm. Hinzu kommt ein Typsystem, das auch jenseits der Nebenläufigkeit vieles abfängt, was in Ruby erst zur Laufzeit auffällt.
Damit hat ein Agent, der Rust schreibt, neben den Tests eine zweite deterministische Instanz, die ihm widerspricht, und zwar genau dort, wo die erste schwach ist. Der Compiler lässt sich nicht „überreden“ und er meldet keinen Erfolg, nur weil der Code plausibel aussieht. Die Strenge, die Menschen an Rust oft als lästig empfinden, wird mit einem Agenten zum Vorteil. Und die Hässlichkeit, die Hansson der Sprache bescheinigt, kostet niemanden mehr etwas.
Wann braucht es noch einen Menschen?
Heißt das, dass Menschen keinen Code mehr lesen müssen? Nein, aber die Frage, wann sie es müssen, bekommt eine andere Antwort als früher. Entscheidend ist für mich dabei die Kritikalität der Software. Bei sicherheitskritischen Systemen, bei kritischer Infrastruktur und überall dort, wo ein Fehler Menschenleben gefährden oder generell großen Schaden jeglicher Art anrichten kann, möchte ich, dass ein Mensch auf den Code schaut, zusätzlich zu allen Tests und zu jedem Compiler.
Den zigmillionsten Webserver in Python muss dagegen niemand mehr Zeile für Zeile von Hand durchsehen, das bekommt ein Agent inzwischen ganz gut eigenständig hin. Und HEY steht auf dieser Skala eher auf der unkritischen Seite: Ein E-Mail-Dienst mag für seine Nutzerinnen und Nutzer wichtig sein – technisch ist er aber überschaubar, und deshalb trägt Hanssons These dort. Auf die Steuerung eines Kraftwerks würde ich sie nicht übertragen.
Bleibt die menschliche Seite, die die Stille im Saal erklärt. Viele Entwicklerinnen und Entwickler definieren sich über ihre Sprache, und für eine Community, deren Selbstverständnis seit gut zwanzig Jahren auf der Freude am Schreiben ruht, ist eine solche Keynote ein Einschnitt.
Ich sehe das relativ nüchtern. Natürlich gibt es Sprachen, die mir besser gefallen als andere (so mag ich zum Beispiel ganz subjektiv C# lieber als Visual Basic), und solche, die ich für gelungener halte (wie zum Beispiel, auch wieder subjektiv, Go deutlich mehr als Python). Kundinnen und Kunden ist es aber in fast allen Fällen gleichgültig, in welcher Sprache ihre Software geschrieben ist: Sie wollen letztlich einfach nur ihr (fachliches) Problem gelöst haben, wie die technische Lösung auch immer aussehen mag.
Dass Teams trotzdem so leidenschaftlich über Technologie streiten, halte ich ohnehin für eines der Grundprobleme vieler Projekte. Es finden zu viele technologische und zu wenige fachliche Diskussionen statt, ein Punkt, den ich in Software ist ein Werkzeug, kein Selbstzweck ausführlich beschrieben habe. Agenten verschärfen diesen Befund nur: Wenn das Schreiben kaum noch etwas kostet, bleibt vom Streit um die schönere Syntax nicht mehr viel übrig.
Was die Sprache nicht mehr entscheidet
Hanssons Keynote hat für Aufregung gesorgt, weil sie an ein Tabu der Branche rührt: dass die Sprache, an der so viel Identität hängt, austauschbar sein könnte. Ich halte die These für richtig, solange sie dort angewendet wird, wo sie hingehört. Wenn Agenten schreiben, entscheidet nicht mehr, welche Sprache Freude macht, sondern was sich deterministisch prüfen lässt, durch Tests und dort, wo Tests an Grenzen stoßen, durch den Compiler. Je kritischer die Software ist, desto mehr braucht es trotzdem (noch) den Menschen.
Eine Frage bleibt dabei allerdings offen, und sie geht in solchen Debatten gern unter. Ob ein Team Ruby oder Rust einsetzt, spielt mit Agenten eine geringere Rolle denn je. Ob ein Problem eine relationale Datenbank braucht, eine dokumentenbasierte oder eine Message-Queue, ist dagegen keine Geschmacksfrage, sondern eine Architekturentscheidung. Genau diese Entscheidung treffen viele Teams, bevor sie das Problem überhaupt kennen, und darum geht es im zweiten Teil dieser Serie.
Lesen Sie auch
(mro)
Entwicklung & Code
Inference Manager: neues Ubuntu-Tool verwaltet lokale KI-Modelle
Mit dem Inference Manager hat Canonical auf der hauseigenen Tagung „Ubuntu Summit“ ein neues Werkzeug vorgestellt, um lokal installierte KI-Modelle zu verwalten. Das Tool stellt den Kommandozeilenbefehl inference bereit, der Modelle auf dem eigenen Computer installiert und verfügbar macht. Über eine HTTP-Schnittstelle können dann Programme auf die KI-Inferenz zugreifen. Laut Canonical ist sie zur OpenAI-API kompatibel, sodass sich bestehende Clients direkt anbinden lassen.
Weiterlesen nach der Anzeige
Mit der aktuellen Ubuntu-Version, 26.10 Stonking Stingray, wurde ein KI-Feature veröffentlicht: Myna ist ein Speech-to-Text-Programm, das auf Desktopsystemen flüssiges Diktieren ermöglicht und das Ergebnis in beliebige Textfelder schreibt. Es setzt auf sogenannte Inference-Snaps auf: Snap ist Ubuntus hauseigenes Paketformat, und im Snap Store sind verschiedene KI-Modelle verfügbar, die komplett auf dem eigenen Gerät laufen und keine Internetverbindung benötigen. Als einheitliche Schnittstelle steht nun der Inference Manager bereit, mit dem Modelle verwaltet werden können. Über TCP-Port 8400 lassen sich alle installierten Modelle ansprechen: Chat-Assistenten auf dem Desktop, Coding-Agenten im Editor oder eben Speech-to-Text-Programme können so auf ihre entsprechenden Modelle zugreifen.

Die Autos werden von einem KI-Modell gesteuert, das Befehle entgegennimmt.
(Bild: Marvin Shah / heise medien)
Auf dem Ubuntu Summit machte Canonical dieses Konzept mit einer Carrera-Bahn erlebbar, bei der KI-Modelle die Autos steuerten. In einer Webapplikation ließen sich verschiedene Modelle auswählen, die „Fahrer“ reagierten auf Sprachbefehle wie „fahr schneller“.

Der „Ubuntu Summit GP“ soll die Möglichkeiten des Inference Managers demonstrieren.
(Bild: Marvin Shah / heise medien)
Der Inference Manager wird als Snap ausgeliefert und kann mit sudo snap install inference oder über das App Center installiert werden. Danach können mit Befehlen wie inference install smollm2 Modelle installiert werden, um sie anschließend zu nutzen. Inference Manager ist ab sofort im Snap Store verfügbar.

Inference Manager verwaltet lokale KI-Modelle.
(Bild: Marvin Shah / heise medien)
Während Teile der Open-Source-Community den Einsatz von KI kontrovers diskutieren, will Canonical bei Ubuntu auf lokal laufende Open-Weight-Modelle setzen. Geplant sind etwa kontextsensitive Hilfe bei der Fehlersuche, bessere Spracherkennung für die Barrierefreiheit und Automatisierungen durch agentische Workflows. Die KI-Funktionen sollen laut Canonical als Opt-in kommen und sich jederzeit deinstallieren lassen.
(ktn)
Entwicklung & Code
AWS Emulator im Detail: Die ganze Cloud auf dem eigenen Rechner?
Amazon Web Services (AWS) hat einen eigenen AWS Emulator veröffentlicht. Er bildet die AWS-APIs auf dem eigenen Rechner nach, AWS CLI, SDKs und Coding-Agenten schicken ihre Aufrufe an einen lokalen HTTPS-Endpunkt. Mit seinem Stolz darauf, dass der Emulator vollständig von KI-Agenten entwickelt wurde, setzte sich AWS aber direkt in die Nesseln: Die Rezeption fiel kritisch aus – wie bei hundertprozentig KI-generierter Software zurzeit üblich – und dem Vergleich mit etablierten Drittanbieter-Tools wie LocalStack hält der Emulator wohl noch nicht stand.
Weiterlesen nach der Anzeige
Entwickler könnte er dennoch interessieren: AWS-Anwendungen lassen sich ohne Deployment lokal testen, CI/CD-Pipelines brauchen keine AWS-Zugangsdaten mehr und – was AWS besonders unterstreicht – Coding-Agenten können schneller und risikoärmer Ressourcen anlegen und Ergebnisse prüfen. AWS bringt also agentisch entwickelte Software für die Entwicklung mit Agenten. Es fällt keine Servicegebühr an, ein AWS-Konto braucht es nicht und der Quellcode steht unter der CC0-Lizenz auf GitHub.
iX-plore ist die Online-Serie des iX-Magazins für alle, die neue Tools und Technologien entdecken möchten. In kurzen Beiträgen stellen wir vor, was sie können, wofür sie sich eignen und warum sich ein genauerer Blick lohnen könnte.
Realismus dank Fidelity-Tests
Der Emulator ist in Rust geschrieben, die Dienste erzeugt AWS aus denselben API-Modellen, aus denen auch die SDKs entstehen. Kommt ein Dienst oder eine API hinzu, tauchen sie im Emulator auf. Alle Dienste, für die ein Modell im öffentlichen Repository AWS API Models liegt, werden auch unterstützt.
Wie genau der Emulator AWS nachbildet, misst AWS mit Fidelity-Tests. Jeder Test ist ein kurzes Python-Programm, das über das AWS-SDK boto3 einen Ablauf durchspielt, etwa ein Objekt zu speichern, zu lesen und wieder zu löschen. Die Abläufe werden dann gegen die echte Cloud geprüft, als Referenz dient die Region US West (Oregon), während globale Dienste in US East (N. Virginia) geprüft werden. Der Emulator besteht einen Test nur, wenn bei jedem Aufruf Statuscode, Antwort, Fehlercode und Fehlermeldung mit der Cloud übereinstimmen, dasselbe gilt für die Ressourcen und Daten, die der Ablauf erzeugt. Die Testsuite umfasst Zehntausende Tests, ist öffentlich und enthält auch die, die noch scheitern. Mit dem Python-Programm fidelity_tests_runner können Nutzer die Tests lokal gegen den Emulator laufen lassen.
Trotz der hohen API-Abdeckung hat die Emulation aber bewusste Grenzen: Für Sicherheitstests eignet sich das Tool laut AWS nicht, da es weder IAM- noch ressourcenbasierte Richtlinien wie die echte Cloud auswertet. Auch Cross-Account- und Cross-Region-Szenarien bildet es nicht ab, sämtliche Aufrufe laufen unter einer festen Dummy-Konto-ID.
Jede Instanz des Emulators bekommt einen eigenen Port, eigene Schlüssel und einen eigenen Zustand im Arbeitsspeicher. Mehrere Agenten oder CI-Jobs teilen sich also keine Buckets, Tabellen oder Queues und arbeiten parallel, ohne sich gegenseitig Ressourcen zu überschreiben. Nutzer des AWS SDK for Rust können den Emulator außerdem im Embedded-Modus betreiben, wobei er direkt ins Test-Binary kompiliert wird. Er läuft dann im selben Prozess und der Test übergibt dem SDK einen HTTP-Client des Emulators statt des Netzwerk-Connectors. Auch hier sind die Instanzen voneinander isoliert, sodass Tests parallel laufen können.
Weiterlesen nach der Anzeige
Installation und Betrieb
Coding-Agenten können den Emulator mit dem Skill aws-emulator direkt installieren, starten und verbinden, dafür braucht es allerdings die AWS CLI ab Version 2.35.0. Solche Skills sind im Prinzip Markdown-Anleitungen, die der Agent bei Bedarf lädt. Der Befehl aws agent-toolkit add-skill in der AWS CLI installiert sie für alle Agenten, die es auf dem Rechner findet. Unter Linux gibt es RPM- und Debian-Pakete, unter Windows und macOS einen Docker-Container. Ein fertiges Docker-Image gibt es nicht, das müssen Nutzer aus einem kurzen Dockerfile aus der Dokumentation zusammenbauen. Standardmäßig sendet der Emulator anonymisierte Nutzungsdaten an AWS, was sich jedoch per Start-Flag oder Umgebungsvariable abschalten lässt.
Wer den Emulator selbst kompiliert, braucht Linux auf x86_64 oder aarch64, eine Rust-Toolchain, einen C-Compiler und mindestens 100 GByte freien Speicherplatz für die Build-Artefakte. Jeder emulierte Dienst ist ein eigenes Rust-Paket (Crate), weshalb schon ein Debug-Build sehr groß wird. Das gilt auch für den Embedded-Modus, denn der erste cargo test-Lauf kompiliert sämtliche Service-Crates des Emulators mit. AWS empfiehlt, das Build-Verzeichnis in der CI zu cachen und den Emulator auf einen Release-Commit festzulegen.
„Vibecode“ von AWS?
Matthew Goldberg, Senior Principal Engineer im Developer-Tools-Team von AWS, setzt mit dem Emulator eine KI-Duftnote: Nicht nur ist die Software vor allem auf das schnelle Testen von agentischer KI zugeschnitten, sondern sie ist laut Amazons Firmenblog auch ausschließlich von autonomen Agenten geschrieben. Das Team hat den Code weder verfasst noch geprüft. Goldberg beschreibt, wie ihn der autonome Bau eines C-Compilers von Agenten dazu inspirierte und der Emulator aus einem simplen Wochenendprojekt hervorging. Ein Team von Agenten pflegt die Testsuite, ein zweites sucht Abweichungen von der echten Cloud, ein drittes setzt die Korrekturen um. Jede Änderung muss zudem vor dem Merge ein automatisiertes Quality Gate passieren, an dem weitere Agenten unter anderem die Sicherheit des Codes kontrollieren.
Die autonome Entwicklung lässt sich in den Repository-Verzeichnissen issues/things-that-now-work und issues/things-that-do-not-work nachvollziehen, in die die Agenten hineinschreiben. Menschliche Hilfe von außen ist dabei nicht vorgesehen: Zwar können Nutzer auf GitHub Fehler melden, Pull-Requests nimmt AWS für das Projekt aber nicht an. Ganz unabhängig von dem Tool an sich ist hier also anschaulich zu sehen, in welche Richtung Softwareentwicklung gerade steuert – und wie die großen Systemhäuser versuchen, Vibe-Coding sinnvoll anzugehen.
(kki)
Entwicklung & Code
Gestohlene Token: Secret-Stealer in Tausenden GitHub-Repositories
Mit gestohlenen Zugriffstoken für GitHub-Konten schleusen unbekannte Angreifer seit Dienstag Schadcode in Repositories ein, der die Secrets aus GitHub Actions und Cloudzugangsdaten abgreift.
Weiterlesen nach der Anzeige
Das Sicherheitsunternehmen Aikido zählt im Rahmen der auf den Namen wfx-loot getauften Kampagne bereits 4837 übernommene Konten, über die die Angreifer 61.764 Repositories attackiert haben. In mehr als 1800 Fällen sollen Workflows den Schadcode bereits ausgeführt haben.
Die Angreifer nutzen anscheinend keine Lücke in GitHub Actions aus, sondern missbrauchen die Schreibrechte gestohlener Token. Woher diese stammen, ist nur teilweise geklärt. Laut Fly.io wurden Token seiner GitHub-App missbraucht, die aus öffentlich erreichbaren .git/config-Dateien stammten; der Hoster widerruft sie. Eine Stellungnahme von GitHub liegt noch nicht vor.
Das Sicherheitsunternehmen SafeDep hat Schadcode-Commits bereits in über 8000 öffentlichen Repositories gefunden. Noch am Donnerstagmittag listete die GitHub-Suche mehr als 66.000 der typischen Test-Pull-Requests, rund 4300 davon vom selben Tag.
Ähnlich wie zuletzt beim Wurm testmetest erreichen Angreifer laut Aikido über Mitwirkenden- und Organisationsrechte mit über 10.000 Test-Pull-Requests auch Repositories, die den übernommenen Konten nicht selbst gehören. Damit können auch Organisationen betroffen sein, deren eigene Zugangsdaten gar nicht gestohlen wurden. Dürfen die Workflows eines Repositorys auf AWS oder Azure zugreifen, nutzt der Schadcode die erbeuteten Zugänge, um Hintertüren in den Cloudkonten einzurichten.
Spuren oft binnen einer Minute verwischt
Die Angreifer lassen ihren Opfern kaum Zeit zu reagieren. Sie öffnen zunächst einen Pull Request, um die Schreibrechte zu bestätigen. Dann folgt der eigentliche Schadcode: ein Shellskript, das die Angreifer in einen bestehenden Workflow einfügen, als neuen Workflow ablegen oder in npm-Projekten bei jeder Installation starten lassen.
Meist schon innerhalb einer Minute machen die Angreifer die Änderungen rückgängig und löschen den Workflow-Lauf samt Logs. Oft weist nur eine fehlende Laufnummer auf den Angriff hin. Eine Branch-Protection für vorgeschriebene Status-Checks kann das Skript mit gefälschten Erfolgsmeldungen aushebeln. Aikido zufolge setzt das Skript solche gefälschten Status-Checks tatsächlich ab; in den von SafeDep untersuchten Proben war diese Funktion dagegen nicht aktiviert.

Mit einem gestohlenen Token testen die Angreifer zuerst ihre Schreibrechte, bevor sie den Stealer auf einem von drei Wegen einschleusen und die Änderung wieder zurücknehmen.
(Bild: SafeDep)
Neben Token für KI-Dienste wie OpenAI, Anthropic oder Cursor fischt das eingeschleuste Skript insbesondere die Secrets aus GitHub Actions ab, außerdem Zugangsdaten für Clouddienste, Container-Umgebungen, Paketregister und SSH.
Weiterlesen nach der Anzeige
Haben die Bedrohungsakteure erst einmal Zugang zu Sitzungen bei AWS, Google Cloud und Azure, geht der Angriff weiter: Bei AWS öffnet das Skript eine IAM-Rolle für jedes AWS-Konto, in Azure trägt es zusätzliche Anmeldewege für Workflows aus dem kompromittierten Repository ein. Erbeutete Daten schickte das Skript laut Aikido in dieser Kampagne per HTTP an Server der Angreifer. SafeDep fand in untersuchten Payloads zudem eine Exfiltration über Telegram.
Selbsttest: Ein Pull Request verrät das gekaperte Konto
Entwicklerinnen und Entwickler, die seit Dienstag einen Branch wfx-docs, den Pull-Request docs: dependency audit notes oder Commits wie ci: refresh build cache, chore: add ci helper und chore: add dependency audit workflow in ihren Repositories finden, sollten das zugehörige Konto als kompromittiert ansehen, auch wenn noch kein Schadcode folgte. Verdächtig sind laut den Sicherheitsforschern von Aikido zudem kurzlebige Branches, die mit chore/ beginnen und auf acht Zufallszeichen enden. Betroffene sollten Token, OAuth-Freigaben und SSH-Schlüssel ihres Kontos widerrufen.
Wurde bereits Schadcode ausgeführt, müssen Betroffene neben dem Austausch der Secrets auch die Hintertüren eigens entfernen, etwa AWS-Rollen, die jedem Konto vertrauen, oder in Azure Federated Credentials mit dem Präfix wfx-ci-. Wer npm install auf einem betroffenen Commit ausgeführt hat, muss auch den eigenen Rechner als kompromittiert betrachten.
Der Schadcode gelangte auch in Paketdistributionen. Aikido nennt das Packagist-Paket digitalelvis/neuronai-studio 3.14.3 sowie die Go-Modul-Versionen github.com/onuragtas/docker-env v1.0.278 und v1.0.280. SafeDep führt darüber hinaus github.com/onuragtas/redock, eine weitere docker-env-Version und eine über den Go-Modul-Proxy verfügbare Pseudo-Version von github.com/vkuznet/gocurl auf. Bei den Go-Modulen liegt der Schadcode in einer GitHub-Actions-Workflow-Datei; ein gewöhnlicher Go-Build führt diese nicht aus. Wer ein solches Modul lediglich als Go-Abhängigkeit einbindet, ist dadurch wahrscheinlich nicht betroffen.
(mro)
-
Apps & Mobile Entwicklungvor 2 Monatentado°: Smartes Wand-Thermostat ersetzt Batterien durch USB‑C‑Akku
-
Apps & Mobile Entwicklungvor 2 MonatenAqara Spatial Multi-Sensor FP400: Matter-Sensor erkennt bis zu 10 Personen mit mmWave‑Radar
-
Apps & Mobile Entwicklungvor 2 MonatenArm CSS for Mobile 2: C2-Ultra macht die CPU zum Orchestrator für KI‑Agenten
-
Künstliche Intelligenzvor 2 MonatenGesperrte Straße von Hormus: Laut Prognose werden CO₂-Emissionen 2026 sinken
-
Künstliche Intelligenzvor 1 MonatVerbrenner-Aus: Merz und Macron wollen CO₂-Ziel für 2035 weiter lockern
-
Künstliche Intelligenzvor 2 Monaten
Plug-in-Hybride emittieren sechsmal mehr CO₂ im Alltag als offiziell angegeben
-
Apps & Mobile Entwicklungvor 3 MonatenDeutsche Lüfter-Ikone: ebm‑papst geht für 5,1 Milliarden Euro in die USA
-
Künstliche Intelligenzvor 2 MonatenDänischer CO₂-Speicher „Greesand“ geht im Meeresgrund in Regelbetrieb
