# Sicherheits-Mutationen der Leistungsbilanz: jede baut gezielt eine Schutzfunktion aus und # muss mindestens einen inhaltlich passenden Test rot machen. Lauf: make mutation # Läuft nur die Sicherheitstests (schnell); Node im node:24-Container, falls lokal kein npm. test_cmd = ["sh", "-c", "if command -v npm >/dev/null; then node --import tsx --test tests/security/baseline.test.ts tests/security/roles.test.ts tests/authentication.test.ts; else docker run --rm -u $(id -u):$(id -g) -e HOME=/tmp -v \"$PWD\":/w -w /w node:24 node --import tsx --test tests/security/baseline.test.ts tests/security/roles.test.ts tests/authentication.test.ts; fi"] workdir = "." [[mutation]] name = "Login-Pflicht für /api entfernt" file = "src/server/app.ts" old = " app.use(\"/api\", createAuthGuard(authConfig, sessionStore, userRepository));\n" new = "\n" [[mutation]] name = "Neue ungeschützte Route vor dem Auth-Guard" file = "src/server/app.ts" old = " app.use(\"/api\", requireSameOriginForWrites());" new = " app.get(\"/api/debug\", (_req, res) => {\n res.json({ ok: true });\n });\n app.use(\"/api\", requireSameOriginForWrites());" [[mutation]] name = "Admin-Rolle für /api/users entfernt" file = "src/server/routes/user.routes.ts" old = "userRouter.use(requireRole(\"admin\"));" new = "" [[mutation]] name = "Passwortwechsel-Pflicht entfernt" file = "src/server/app.ts" old = " app.use(\"/api\", requirePasswordChanged());\n" new = "\n" [[mutation]] name = "CSRF-Header-Prüfung entfernt" file = "src/server/auth/auth.middleware.ts" old = " if (req.get(WRITE_REQUEST_HEADER_NAME) !== WRITE_REQUEST_HEADER_VALUE) {" new = " if (false) {" [[mutation]] name = "Unbekannte Felder erlaubt (Mass Assignment)" file = "src/shared/validation/project-structure.schemas.ts" old = " threePhaseVoltageV: z.number().positive().optional(),\n}).strict();" new = " threePhaseVoltageV: z.number().positive().optional(),\n});" [[mutation]] name = "Kaputtes JSON führt wieder zu 500" file = "src/server/middleware/error.middleware.ts" old = " if (status !== undefined) {" new = " if (false) {" [[mutation]] name = "Fehlertext an Client durchgereicht" file = "src/server/middleware/error.middleware.ts" old = " res.status(500).json({ error: \"Internal Server Error\" });" new = " res.status(500).json({ error: String((error as Error).stack) });" [[mutation]] name = "CORS für alle Origins" file = "src/server/app.ts" old = " app.disable(\"x-powered-by\");" new = " app.disable(\"x-powered-by\");\n app.use((_req, res, next) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n next();\n });" [[mutation]] name = "nosniff-Header entfernt" file = "src/server/app.ts" old = " res.setHeader(\"X-Content-Type-Options\", \"nosniff\");" new = "" [[mutation]] name = "X-Powered-By wieder an" file = "src/server/app.ts" old = " app.disable(\"x-powered-by\");" new = ""