Die Lektion für 35.000 Pfund: wenn KI generierter Code auf die Produktion trifft
Kurz gesagt
Niveau: Fortgeschritten
Zwei Anbieter haben ihren Code von KI schreiben lassen und ungeprüft ausgeliefert. In einem Monat hat das meine Kunden mehr als 35.000 Pfund gekostet.
- Projekt eins: keine Tests, Antworten, die täglich ihre Form ändern, ein Endpunkt für die Bestellhistorie ohne Authentifizierung, Endpunkte, die ohne Hinweis wandern.
- Projekt zwei: sieben Rabattberechnungen in drei Wochen, eine Validierung, die es sich anders überlegt, mehrdeutige Datumsangaben.
- Die Kosten: 18.500 Pfund meiner Zeit, 8.200 Pfund für Ausfälle, 4.800 Pfund für den Abgleich, 2.100 Pfund Entschädigung, bisher 1.400 Pfund für ein Sicherheitsaudit.
- Dein Schutz: Prüf jede Antwort an deiner Grenze gegen einen vereinbarten Vertrag, stell in Quarantäne, was durchfällt, und schreib Versionierung und Fristen für Abkündigungen in den Vertrag.
In einem Monat haben zwei Drittanbieter, die ihren Code ungeprüft von KI schreiben ließen, meine Kunden mehr als 35.000 Pfund gekostet. Das ist die Nachbetrachtung: wie die Integrationen aussahen, was jeder Teil gekostet hat, auf welche Code Smells ich inzwischen achte und wie du das Chaos eines Anbieters am Rand deines eigenen Systems aufhältst.
Ein Monat, zwei Anbieter, 35.000 Pfund
Im vergangenen Monat habe ich zugesehen, wie zwei voneinander unabhängige Projekte im Chaos versanken, weil Drittanbieter beschlossen hatten, dass KI generierter Code für die Produktion gut genug sei. Das Ergebnis bisher: mehr als 35.000 Pfund direkte Kosten für meine Kunden, sehr viele Stunden, in denen ich die erfundene Logik anderer Leute debuggt habe, und der Grund, warum ich ein kleines Werkzeug gebaut habe, das Code markiert, der einen genaueren Blick braucht.
Das ist kein theoretischer Text darüber, ob KI Code schreiben kann. Es ist eine Nachbetrachtung dessen, was passiert, wenn eine Organisation KI generierten Code als Abkürzung behandelt statt als Ausgangspunkt. Die Projekte sind echt, und ich habe alles geändert oder weggelassen, woran man sie erkennen könnte.
Zwei Projekte, dasselbe Problem
Ich arbeite an zwei großen eCommerce Integrationen: eine für einen Schmuckhändler in den USA, eine für eine Modeplattform in Großbritannien. Beide hängen für kritische APIs und Dienste von Drittanbietern ab. Und beide Anbieter, so stellt sich heraus, lesen "KI gestützte Entwicklung" als "lass die KI alles schreiben und hoff auf das Beste".
Die Symptome waren verschieden. Die Ursache war dieselbe.
Projekt eins: eine Schmuckplattform in den USA
Hier geht es ums Skalieren. Während ich die Integration ausbaue, muss der Anbieter mitwachsen. Er beschreibt seine Arbeitsweise als Rapid Development Framework, was, soweit ich das erkennen kann, heißt: Ein KI Modell schreibt den Code, und er geht raus, ohne dass jemand hinsieht. (Das ist nicht, was der Begriff bedeutet. Ich habe in der Woche davor darüber geschrieben, was Rapid Development Frameworks wirklich sind.)
Nichts ist getestet
Nicht "die Abdeckung ist etwas niedrig". Es gibt überhaupt keine Tests. Die KI hat die Umsetzung erzeugt, jemand hat kurz draufgeschaut, und sie ging in Produktion.
Als ich nach der Teststrategie gefragt habe, hieß es, KI generierter Code sei von Natur aus zuverlässiger, weil er auf Mustern aus Millionen von Codebasen beruhe. So funktioniert nichts davon.
Die praktische Folge: Jeder Teil meiner Integration muss damit rechnen, dass ihre API etwas Unerwartetes zurückgibt. Ich habe einen Endpunkt für Produkte gesehen, der den Preis als String, als Integer, als Float und einmal als verschachteltes Objekt mit dem Preis drei Ebenen tiefer geliefert hat. Alles vom selben Endpunkt, in derselben Woche.
Antworten ändern ihre Form von einem Tag auf den anderen
Das ist das Erkennungszeichen von Code, der neu erzeugt statt gepflegt wird.
- Montag:
/api/products/{id}liefert{ "name": "Diamond Ring", "price": 1299 } - Mittwoch: derselbe Endpunkt liefert
{ "product_name": "Diamond Ring", "price_cents": 129900 } - Freitag:
{ "title": "Diamond Ring", "pricing": { "amount": 1299, "currency": "USD" } }
Keine Versionierung, kein Hinweis auf Abkündigung. Das Schema ändert sich, weil jemand die KI gebeten hat, den Endpunkt zu "verbessern", und sie entschieden hat, das heiße, die Antwort umzubauen. Meine Integration kommt jetzt mit allen dreien zurecht, weil ich nicht wissen kann, welche ich bekomme.
Die API ist nicht sicher
Die Authentifizierung trägt die Kennzeichen von erzeugtem Sicherheitscode, den niemand geprüft hat. API Schlüssel werden bei manchen Endpunkten im Client geprüft, bei anderen auf dem Server. Ein Endpunkt nimmt eine user_id entgegen und liefert die komplette Bestellhistorie dieses Nutzers, samt Zahlungsdaten, ganz ohne Prüfung der Authentifizierung. Die "Admin" Endpunkte sind dadurch geschützt, dass geprüft wird, ob im Header einer Anfrage X-Admin: true steht. Das ist das gesamte Sicherheitsmodell.
Der Endpunkt mit user_id ist ein Lehrbuchfall dessen, was die OWASP API Security Top 10 an erster Stelle führen: fehlerhafte Autorisierung auf Objektebene, bei der eine API einer vom Client geschickten Objekt Id vertraut und nie prüft, ob der Aufrufer dieses Objekt sehen darf.1 Der Admin Header ist fehlerhafte Authentifizierung in ihrer schlichtesten Form.2
Ich habe diese Probleme mehrmals gemeldet. Die Antwort: "Wir lassen die KI die Sicherheitsumsetzung prüfen." Dieselbe KI, die sie geschrieben hat.
Endpunkte wandern ohne Vorwarnung
Letzten Dienstag ist die Hälfte meiner Integration ausgefallen, weil aus /api/v2/inventory plötzlich /api/inventory/v2 wurde. Keine Weiterleitung, keine Übergangsfrist, kein Hinweis. Die Erklärung: Das Routing sei "für eine bessere Ordnung umgebaut" worden, auf Vorschlag der KI. Ich prüfe jetzt alle fünf Minuten, ob die Endpunkte erreichbar sind, weil ich nicht darauf vertrauen kann, dass die URLs von heute morgen noch existieren.
Projekt zwei: eine Modeplattform in Großbritannien
Hier ist das Skalieren nicht das Problem. Das Problem ist, dass ich mich auf keine Eingabe und keine Ausgabe verlassen kann, weil sich die Logik darunter ständig ändert.
Logik, die sich zwischen zwei Deployments ändert
Der Endpunkt für Rabatte ist das deutlichste Beispiel. Über drei Wochen habe ich sieben verschiedene Berechnungsarten dokumentiert:
- Erste Woche: Prozente vom Listenpreis.
- Später in derselben Woche: Prozente nach Mehrwertsteuer.
- Zweite Woche: ein fester Betrag weniger, abgerundet.
- Später in derselben Woche: ein fester Betrag weniger, auf den nächsten Penny gerundet.
- Dritte Woche: Prozente weniger, gedeckelt bei 50 Pfund.
- Später: Prozente weniger, mit einem Mindestrabatt von 5 Pfund.
- Noch später: zurück zu Prozenten vom Listenpreis, aber mit anders berechneter Mehrwertsteuer.
Keine davon kam mit Dokumentation, einem Changelog oder einem Hinweis. Jemand hat die KI gebeten, "die Rabattberechnung zu reparieren", und sie hat die Berechnung von Grund auf neu geschrieben, so wie es ihr an diesem Tag vernünftig erschien.
Validierung, die es sich anders überlegt
Eingaben, die gestern funktioniert haben, liefern heute einen Fehler 400. Eingaben, die scheitern sollten, werden angenommen und beschädigen die Daten. Ich habe gesehen:
- eine Prüfung von Mailadressen, die am Montag
not-an-emailakzeptiert und am Dienstagvalid@example.comabgelehnt hat, weil ein neues Muster eine Top Level Domain aus zwei Buchstaben verlangte, - Preisfelder, die negative Zahlen annehmen, sodass eine Bestellung den Kunden fürs Kaufen bezahlen könnte,
- eine Datumsverarbeitung, die
01/02/2025an manchen Tagen als 2. Januar und an anderen als 1. Februar las, je nachdem, welche erzeugte Funktion gerade ausgeliefert war.
Die Code Smells, die ich immer wieder sehe
Beide Codebasen zeigen die Muster, wegen derer ich meinen Detektor gebaut habe. Die Ausschnitte unten veranschaulichen sie.
Kommentare, die das Offensichtliche wiederholen:
# This function calculates the total price by adding up all the item prices
def calculate_total_price(items):
# Initialize the total to zero
total = 0
# Loop through each item in the items list
for item in items:
# Add the item's price to the total
total += item.price
# Return the calculated total
return total
Ein perfekter Docstring an einer trivialen Funktion:
def add(a, b):
"""
Adds two numbers together.
Args:
a: The first number to add.
b: The second number to add.
Returns:
The sum of a and b.
"""
return a + b
Fehlerbehandlung, die alles fängt und nichts behandelt:
try:
result = process_order(order)
except ValueError:
pass # Handle value error appropriately
except Exception:
pass # Handle any other errors appropriately
Ein TODO über Code, der schon da ist:
# TODO: Implement order processing
def process_order(order):
validate_order(order)
calculate_totals(order)
process_payment(order)
send_confirmation(order)
return order
Keines davon ist für sich ein Beweis. Ein sorgfältiger Mensch kann jedes davon schreiben. Zusammen, und überall, sagen sie dir, dass niemand den Code gelesen hat, bevor er ausgeliefert wurde.
Was es bisher gekostet hat
So viel hat das meine Kunden im vergangenen Monat gekostet:
| Posten | Kosten |
|---|---|
| Meine Zeit für Debugging, Umgehungen und defensiven Code und für Vorfälle durch Änderungen beim Anbieter | 18.500 Pfund |
| Drei größere Ausfälle durch unerwartete Änderungen an der API: Notfalleinsatz, Kommunikation mit Kunden, Bestellungen von Hand bearbeitet | 8.200 Pfund |
| Abgleich der Daten: Die Bestellsummen in meinem System passten nicht zu ihren, und der Abgleich eines Monats an Transaktionen hat zwei Leute drei volle Tage gekostet | 4.800 Pfund |
| Entschädigung von Kunden: falsche Preise, gescheiterte Zustellungen, als sich die Prüfung der Adressen mitten in der Woche änderte, falsche Produkte, als sich der Umgang mit SKUs änderte | 2.100 Pfund |
| Sicherheitsaudit durch einen Dritten nach den Befunden zur Authentifizierung, läuft noch | bisher 1.400 Pfund |
| Summe | 35.000 Pfund, Tendenz steigend |
Das sind Pfund, und darin fehlen die Funktionen, die ich nicht bauen konnte, während ich Brände gelöscht habe.
Warum ich einen Detektor gebaut habe
Nach der dritten Woche brauchte ich einen schnellen Weg, um einzuschätzen, ob eine neue Codelieferung dieser Anbieter wahrscheinlich von KI erzeugt war. Nicht, weil KI generierter Code an sich schlecht ist, sondern weil KI generierter Code, den niemand geprüft, getestet oder verstanden hat, eine Belastung ist.
Also habe ich ai-code-dedector gebaut, ein heuristisches Werkzeug, offen auf GitHub.3 Es sucht nach den Erkennungszeichen:
- Stil der Kommentare: ausschweifend, wiederholt das Offensichtliche, absichernde Formulierungen wie "you may want to consider",
- Sättigung mit Docstrings: jede Funktion dokumentiert, egal wie trivial,
- Muster bei Namen: überall lange, voll ausgeschriebene Namen,
- Fehlerbehandlung: übervorsichtige Muster und leere Blöcke
except, die versprechen, "angemessen zu behandeln", - gleichförmige Struktur: jede Funktion nach demselben Muster gebaut,
- verräterische Stellen: ein TODO über einer funktionierenden Umsetzung.
Perfekt ist es nicht. KI Code, den ein Mensch sorgfältig überarbeitet hat, erkennt es nicht, und ein kurzer Ausschnitt gibt ihm wenig zum Arbeiten. Aber es hilft bei der Entscheidung, welcher Code einen zusätzlichen Blick braucht, bevor ich ihn auch nur in die Nähe der Produktion lasse.
Die Risiken hinter der Rechnung
Die Kosten oben sind der sichtbare Teil. Die Risiken darunter machen mir mehr Sorgen.
Schulden, die sich vervielfachen. Ein Anbieter, der Code neu erzeugt, pflegt keine Codebasis, er erzeugt jedes Mal eine neue. Niemand weiß, warum die Dinge so sind, wie sie sind, und jede "Korrektur" bringt woanders Widersprüche.
Sicherheit als Nachgedanke. Bitte ein Modell, "Authentifizierung hinzuzufügen", und du bekommst vielleicht etwas, das wie Authentifizierung aussieht. Ohne Prüfung durch jemanden, der Sicherheit versteht, gehen die Schwächen direkt in Produktion, so wie hier.
Eine Wissenslücke. Die Leute, die diese Systeme pflegen, können sie nicht debuggen, weil sie sie nie verstanden haben. Sie können nur neu erzeugen und hoffen.
Abhängigkeit. Bist du einmal mit einem Anbieter verbunden, der so arbeitet, ist Gehen teuer und Bleiben auch.
Den allgemeinen Fall habe ich an anderer Stelle ausführlich beschrieben, mit den Studien dahinter, deshalb wiederhole ich ihn hier nicht. KI schreibt den Code. Wer ist dafür verantwortlich? behandelt, was schiefgeht und wer dafür einsteht, und wird KI wie ChatGPT je Entwickler ersetzen sieht sich an, was die kontrollierten Studien über KI und die Produktivität von Entwicklern sagen.
Deine Seite einer Integration schützen
Den Prozess eines Anbieters kannst du nicht reparieren. Du kannst dafür sorgen, dass sein Chaos an deiner Grenze endet.
Beispiel: eine Vertragsprüfung an der Grenze
Stubenwerk ist ein erfundener Shop für Wohnaccessoires in Köln, unter stubenwerk.example, der Produkte über die API eines Lieferanten bezieht. Seine Integration traut der Antwort nicht. Jedes Produkt läuft durch eine kleine Klasse, die die vereinbarte Form kennt, und alles andere landet in Quarantäne, statt in den Shop zu gelangen:
class SupplierProduct
Result = Struct.new(:ok, :name, :price_cents, :error, keyword_init: true)
def self.parse(json)
name = json["name"]
price = json["price_cents"]
return Result.new(ok: false, error: "missing name") unless name.is_a?(String) && !name.empty?
return Result.new(ok: false, error: "price is not a whole number of cents") unless price.is_a?(Integer)
return Result.new(ok: false, error: "price is not positive") unless price.positive?
Result.new(ok: true, name: name, price_cents: price)
end
end
result = SupplierProduct.parse(response_json)
if result.ok
ProductSync.upsert(result)
else
SupplierQuarantine.record(response_json, reason: result.error) # und einen Menschen alarmieren
end
Schick die drei Formen aus Projekt eins hindurch, mit einem vereinbarten Vertrag aus name und price_cents:
- Die vom Montag,
{ "name": "Diamond Ring", "price": 1299 }: Es gibt keinprice_cents, also landet sie in Quarantäne mit "price is not a whole number of cents". - Die vom Mittwoch,
{ "product_name": "Diamond Ring", "price_cents": 129900 }: Es gibt keinname, also landet sie in Quarantäne mit "missing name". - Das verschachtelte Objekt
pricingvom Freitag: keinname, Quarantäne.
Der Shop verkauft weiter zum richtigen Preis von gestern, und ein Mensch bekommt schon bei der ersten fehlerhaften Antwort einen Alarm statt bei der hundertsten eine Beschwerde von Kunden. Dieselbe Idee löst das Problem mit den Datumsangaben: Vereinbare ein Format, das sich nicht falsch lesen lässt, etwa 2025-02-01 nach ISO 8601, und lehne alles andere ab.
Was in den Vertrag gehört
Frag, wie der Anbieter entwickelt, prüft und testet. Halte Stabilität schriftlich fest: versionierte Endpunkte, eine Frist vor jeder Entfernung und ein maschinenlesbares Signal, wenn es so weit ist. Die IETF hat Spezifikationen für dieses Signal veröffentlicht: Der Header Deprecation aus RFC 9745 sagt, dass eine Ressource abgekündigt ist oder sein wird,4 und der Header Sunset aus RFC 8594 sagt, wann sie nicht mehr antworten wird.5 Ein Anbieter, der keinen von beiden schickt, hat dir damit gesagt, wie er dich behandeln wird.
Was sich ändern muss
Ich bin nicht gegen KI. Ich nutze KI Werkzeuge in meiner eigenen Entwicklung jeden Tag. Aber es ist ein großer Unterschied, ob du KI als Werkzeug nutzt oder als Ersatz für Verständnis.
Für Anbieter: KI generierter Code ist ein erster Entwurf, kein fertiges Produkt. Er braucht Review, Tests und vor allem Verständnis. Wenn die Leute, die den Code pflegen, nicht erklären können, warum er funktioniert, gehört er nicht in die Produktion.
Für Unternehmen, die Drittanbieter anbinden: Frag nach den Entwicklungspraktiken, schreib Stabilität in den Vertrag, bau Integrationen, die mit Instabilität beim Anbieter rechnen, und überwache Änderungen.
Für die Branche: Erwartungen, keine Verbote. Code Review ist weiterhin nötig. Tests sind weiterhin nötig. Dokumentation, die die Absicht erklärt, nicht nur was der Code tut, sondern warum, ist weiterhin nötig.
Was ich als Nächstes für den Detektor geplant hatte
Als ich das schrieb, wollte ich den Detektor erweitern: um eine Weboberfläche, damit niemand das Repository klonen und ein Terminal benutzen muss, um eine Anbindung an GitHub, die ganze Repositorys scannt, um eine Analyse der Git Historie, weil ein plötzlicher Wechsel im Stil oder in den Mustern der Commits selbst ein Erkennungszeichen ist, und um Berichte pro Datei, die zeigen, welche Teile einer Codebasis am verdächtigsten aussehen.
Das Ziel ist nicht, KI aus der Entwicklung zu verbannen. Es ist, die Stellen zu finden, an denen KI generierter Code die Aufmerksamkeit eines Menschen braucht, bevor er einen Monat wie den verursacht, den ich gerade hinter mir habe.
Bis dahin pflege ich defensiven Code gegen zwei APIs, die ihr Verhalten jederzeit ändern können, und sehe zu, wie die Kosten steigen. 35.000 Pfund in einem Monat, für Code, den bei diesen Anbietern niemand wirklich versteht.
Die beschriebenen Projekte sind echt. Erkennbare Details wurden geändert oder weggelassen. Die Kosten sind zum Zeitpunkt des Schreibens korrekt.
Footnotes
-
OWASP Foundation, API1:2023 Broken Object Level Authorization, OWASP API Security Top 10 2023, https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
-
OWASP Foundation, API2:2023 Broken Authentication, OWASP API Security Top 10 2023, https://owasp.org/API-Security/editions/2023/en/0xa2-broken-authentication/
-
Georg Keferböck, ai-code-dedector, GitHub Repository, angelegt am 13. April 2026, https://github.com/keferboeck/ai-code-dedector
-
S. Dalal und E. Wilde, RFC 9745: The Deprecation HTTP Response Header Field, IETF, März 2025, https://www.rfc-editor.org/rfc/rfc9745.html
-
E. Wilde, RFC 8594: The Sunset HTTP Header Field, IETF, Mai 2019, https://www.rfc-editor.org/rfc/rfc8594.html