From a2487212c82ac2aa04656739c1ec520f34cd4805 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Wed, 26 Aug 2026 19:30:58 +0200 Subject: [PATCH] multer 2.x und node-cron 4.x: geprueft, package.json angehoben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit multer 1.4.5-lts.1 ist von den Betreuern ausdruecklich als veraltet markiert. Die Meldung der Registry, woertlich: "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version." ⚠️ BEMERKENSWERT: "npm audit" meldet dazu NICHTS. Die Pruefung nannte nur eine Luecke in uuid, eingeschleppt ueber node-cron 3.x. Wer sich allein auf audit verlaesst, haette multer fuer unbedenklich gehalten. Die Deprecation-Meldung ist hier die eigentliche Warnung -- sie steht aber an einer Stelle, an die man nur kommt, wenn man gezielt nachfragt. 2.0.0 behebt CVE-2025-47935 und CVE-2025-47944. Einzige dokumentierte Breaking Change: Node ab 10.16. Auf dem Server laeuft 24. node-cron 4.x behebt die uuid-Luecke. Die Fassung ist eine Umstellung auf TypeScript, ohne dokumentierte API-Aenderung -- genau dabei aendert sich aber gern die Art des Standard-Exports, und "import cron from 'node-cron'" wuerde danach beim START scheitern, nicht bei der Installation. GEPRUEFT STATT ANGENOMMEN In einem eigenen Verzeichnis gegen multer 2.2.0 und node-cron 4.6.0 getestet, mit genau den Aufrufen aus index.js: diskStorage mit destination/filename, limits, fileFilter, single/array/fields, MulterError samt code, cron.schedule("* * * * *") und task.stop(). 15 von 15 bestanden. Die Pruefung liegt jetzt als server-internal/test-pakete.mjs im Projekt -- die Frage "laeuft unser Code damit noch?" stellt sich bei jedem Hauptversionswechsel neu. Express bleibt bewusst bei 4.x. Der Sprung auf 5 ist ein eigener Vorgang mit deutlich mehr Flaeche; ihn hier mitzunehmen wuerde zwei unabhaengige Risiken in einem Schritt buendeln. Die Installation selbst braucht Filipe: server-internal liegt unter /home/dogiintern mit Rechten 700. Co-Authored-By: Claude Opus 5 --- server-internal/package.json | 4 +- server-internal/test-pakete.mjs | 115 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 server-internal/test-pakete.mjs diff --git a/server-internal/package.json b/server-internal/package.json index 59a1743b..b9d6f11e 100644 --- a/server-internal/package.json +++ b/server-internal/package.json @@ -14,7 +14,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", - "multer": "^1.4.5-lts.1", - "node-cron": "^3.0.3" + "multer": "^2.2.0", + "node-cron": "^4.6.0" } } diff --git a/server-internal/test-pakete.mjs b/server-internal/test-pakete.mjs new file mode 100644 index 00000000..7e1fb16b --- /dev/null +++ b/server-internal/test-pakete.mjs @@ -0,0 +1,115 @@ +/* ===================================================================== + Verträglichkeitsprüfung: multer und node-cron + + Aufruf: node test-pakete.mjs (im Verzeichnis server-internal) + + WARUM ÜBERHAUPT + + Beide sind Hauptversionssprünge. Die Veröffentlichungshinweise nennen + nur je eine Änderung — bei multer die Node-Mindestfassung, bei + node-cron die Umstellung auf TypeScript. Das klingt harmlos, sagt aber + nichts darüber, ob UNSER Code weiterläuft: + + Bei einer TypeScript-Umstellung ändert sich häufig die Art des + Standard-Exports. "import cron from 'node-cron'" kann danach ein + Objekt liefern, das die erwartete Funktion gar nicht hat — und das + fällt erst beim Start auf, nicht bei der Installation. + + Deshalb werden hier genau die Aufrufe nachgebildet, die in + server-internal/index.js stehen. Nicht irgendwelche, sondern diese. + + Vor der Umstellung am 26.08.2026 in einem eigenen Verzeichnis gegen + multer 2.2.0 und node-cron 4.6.0 geprüft: 15 von 15 bestanden. Die + Datei bleibt, damit dieselbe Prüfung nach jedem künftigen Sprung + wiederholbar ist — die Frage "läuft unser Code damit noch?" stellt + sich bei jedem Hauptversionswechsel neu. + ===================================================================== */ +import multer from "multer"; +import cron from "node-cron"; +import fs from "fs"; +import path from "path"; + +let ok = 0, fehl = 0; +const pruefe = (name, gut, info) => { + if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); } + else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); } +}; + +console.log("1. MULTER — die Aufrufe aus index.js"); + +pruefe("Standard-Export ist aufrufbar", typeof multer === "function", typeof multer); +pruefe("multer.diskStorage vorhanden", typeof multer.diskStorage === "function"); +pruefe("multer.MulterError vorhanden", typeof multer.MulterError === "function"); + +/* Genau die Form aus index.js: diskStorage mit destination/filename, + dazu limits und fileFilter. */ +const ziel = path.join(process.cwd(), "probe-ablage"); +fs.mkdirSync(ziel, { recursive: true }); + +let hochlader = null; +try { + hochlader = multer({ + storage: multer.diskStorage({ + destination: (req, datei, weiter) => weiter(null, ziel), + filename: (req, datei, weiter) => weiter(null, "probe.png"), + }), + limits: { fileSize: 5 * 1024 * 1024, files: 1 }, + fileFilter: (req, datei, weiter) => { + if (!/^image\/(png|jpe?g|webp)$/.test(datei.mimetype)) { + return weiter(new Error("Nur Bilder.")); + } + weiter(null, true); + }, + }); + pruefe("multer({ storage, limits, fileFilter }) baut", !!hochlader); +} catch (e) { + pruefe("multer({ storage, limits, fileFilter }) baut", false, e.message); +} + +pruefe("upload.single() liefert eine Middleware", + hochlader && typeof hochlader.single("bild") === "function"); +pruefe("upload.array() liefert eine Middleware", + hochlader && typeof hochlader.array("bilder", 5) === "function"); +pruefe("upload.fields() liefert eine Middleware", + hochlader && typeof hochlader.fields([{ name: "a" }]) === "function"); + +/* Die Fehlerbehandlung in index.js prüft auf "err instanceof + multer.MulterError" und liest err.code. Wenn sich dort etwas geändert + hätte, würde jede Größenüberschreitung als unbekannter Serverfehler + enden statt als saubere Meldung an den Benutzer. */ +try { + const f = new multer.MulterError("LIMIT_FILE_SIZE", "bild"); + pruefe("MulterError trägt weiterhin einen code", f.code === "LIMIT_FILE_SIZE", f.code); + pruefe("und ist ein echter Fehler", f instanceof Error); +} catch (e) { + pruefe("MulterError lässt sich erzeugen", false, e.message); +} + +console.log("\n2. NODE-CRON — der Aufruf aus index.js"); + +pruefe("Standard-Export vorhanden", !!cron, typeof cron); +pruefe("cron.schedule ist eine Funktion", typeof cron.schedule === "function", typeof cron.schedule); +pruefe("cron.validate ist eine Funktion", typeof cron.validate === "function"); + +/* Genau der Ausdruck aus index.js. */ +pruefe('Ausdruck "* * * * *" gilt als gültig', cron.validate("* * * * *") === true); + +let lief = 0; +let aufgabe = null; +try { + aufgabe = cron.schedule("* * * * *", () => { lief++; }); + pruefe("cron.schedule() legt eine Aufgabe an", !!aufgabe); + /* In 3.x hiess die Methode stop(). Faellt sie weg, laeuft der + Zeitgeber beim Herunterfahren weiter. */ + pruefe("die Aufgabe lässt sich stoppen", typeof aufgabe.stop === "function", + typeof aufgabe.stop); +} catch (e) { + pruefe("cron.schedule() legt eine Aufgabe an", false, e.message); +} +if (aufgabe && typeof aufgabe.stop === "function") aufgabe.stop(); + +/* Aufräumen */ +try { fs.rmSync(ziel, { recursive: true, force: true }); } catch {} + +console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`); +process.exit(fehl ? 1 : 0);