Kommentar zu Log4j: Es funktioniert wie spezifiziert

NOTABUG, WONTFIX

Inhaltsverzeichnis

Aber im Ernst: Viele behandeln den log4j-Exploit wie einen Bug, einen Programmierfehler, eine Verletzung einer Spezifikation. Genau das ist jedoch nicht der Fall: Es funktioniert – wortwörtlich – endlich einmal alles wie spezifiziert und dokumentiert: All die Modularität und dynamische Erweiterbarkeit von Java hat ganz wunderbar und genau wie geplant zusammengearbeitet und funktioniert. Darauf haben wir dekadenlang hingearbeitet! "NOTABUG, WONTFIX"

Und das ist das eigentliche Problem hier. Viele rufen jetzt nach "Mehr Kontrolle!", "Mehr Review!", "Mehr Funding!", "Mehr Augen auf den Code!". Was wirklich helfen würde, wäre weniger Code, weniger Indirektion und Boilerplate, und einfach mehr… Einfachheit.

Wieso brauche ich ein LogAppenderFactorySingleton, das XML liest, um den Namen der Klasse zu bekommen, die es instanziieren muss, damit ich meine Logzeile da einwerfen kann, um sie asynchron an einen LogStream anzuhängen? Das ist nicht einfach. Was ist einfach? JSON nach stderr drucken. Das ist einfach. Aber Firmen stellen seit etwa einer Dekade Leute ein, die nicht wissen, was stdout und stderr sind und das ist irgendwie okay, weil inzwischen ja sowieso alles ein Webservice ist.

Softwareentwicklung ist viel moderner geworden: Wir haben Merge Requests mit Code Review, CI/CD-Pipelines, Infrastructure as Code und Immutable Infrastructure. Das nützt nur nix, wenn meine Java Logging Library auf dem Mars Code von Directory-Servern auf der Erde nachlädt und so das "Remote" in RCE komplett neu definiert. Die Analyse von Dependencies hat nur dann Sinn, wenn die Liste dieser Abhängigkeiten endlich und genau so immutable wie die Infrastruktur ist.

Java hatte einmal die notwendigen Kontrollknöpfe, mit denen wir erzwingen konnten, dass diese Liste von Abhängigkeiten endlich und unveränderlich ist. Wenn man auf diese Art von Lebensstil steht, gibt es etwas, das sich SM nennt: Oracle SM.

SM bringt die notwendigen Verträge und die Disziplin, die eine Codebase braucht. Aber die meisten Anwender stehen nicht auf SM und lehnen die Idee ab. Also wird die Funktionalität in Java 17 als deprecated (veraltet) gekennzeichnet und später entfernt werden (JEP 411: Deprecate the Security Manager for Removal).

(Bild: imgflip.com)

Auch JNDI hat SM abgelehnt und hat ein promiskuitives Interface, das Code irgendwoher lädt und ausführt. Man muss sich das wie einen Dreijährigen vorstellen, der sich jede Klasse in den Mund steckt, um herauszufinden, wie sie schmeckt und ob sie sich ausführen lässt.

Das ist am Ende genau die Spezifikation: Hier ist ein Object, deserialisiere es. In Java bedeutet das, dass der Code für die Klasse des Objektes irgendwoher kommen muss, deren Methoden dann ausgeführt werden. Natürlich würde niemand das für eine gute Idee halten, wenn man es so formuliert. Aber andererseits hat es die Person, die das vor acht Jahren implementiert hat, nicht gesehen, und auch die Hunderttausend, die log4j in ihre Codebasis importiert haben, sind nicht darüber gestolpert.

Was sagt uns das über den Dependency-Management-Prozess von Organisationen, die Software entwickeln? Über das Verständnis der Codebase, der Abhängigkeiten und der Prozesse, die Datenfluss und Releases planen? Ja, genau. "Wir verwenden eine modulare Architektur und agile Methoden, um die Entwicklungsgeschwindigkeit zu steigern."

E = 1/2m*(v^2)

Mehr Entwicklungsgeschwindigkeit macht größere Krater.

Ganz besonders nicht dynamisch aus dem Internet nachgeladener Code.

Code. Ist. Nicht. Dein. Freund.

Ich weiß, es klingt komisch, wenn man Entwickler ist und den eigenen Lebensunterhalt damit bestreitet, dass man glaubt, man sei mit dem Code befreundet.

Aber so ist es. Weniger Code ist besserer Code. Am besten so wenig Code, dass man ihn zur Gänze und mit all seinen Interaktionen verstehen kann. Und auch den Code, der notwendig ist, um den eigenen Code zu betreiben.

(map)