diff --git a/server/index.js b/server/index.js index d8e22012..4a70f314 100644 --- a/server/index.js +++ b/server/index.js @@ -37,6 +37,40 @@ app.use(cookieParser()); app.use(express.json({ limit: "1mb" })); app.use(gateMiddleware); +/* Sicherheits-Fix 20.08.2026 (Audit vor dem geplanten öffentlichen Start morgen). + SITE_DIR ist der GESAMTE Repo-Ordner (join(__dirname, "..")) — express.static liefert + ohne diese Sperre daher nicht nur die eigentliche Website aus, sondern auch den Server- + Quellcode (server/, server-internal/, cloudflare-worker/) und das komplette + .git-Verzeichnis samt Commit-Historie. + Live nachgewiesen (mit gültigem Zugangscode, der morgen für alle wegfällt): + /server/gate.js und /.git/config lieferten HTTP 200. Ursache: serve-static blockt per + Voreinstellung nur Dateien, deren EIGENER Name mit einem Punkt beginnt (server/.env -> + 404 durch diese Regel) — aber NICHT rekursiv. Eine Datei wie .git/config wird trotzdem + ausgeliefert, weil "config" selbst nicht mit einem Punkt beginnt, nur der Ordnername davor. + Diese Sperre läuft daher bewusst unabhängig von gateMiddleware (bleibt auch nach dem + morgigen Entfernen der Zugangsschranke wirksam) und blockt ganze Ordner/Muster statt + einzelner Dateien, damit neue Dateien darin automatisch mitgeschützt sind. */ +const GESPERRTE_ORDNER = ["/server", "/server-internal", "/cloudflare-worker"]; +const GESPERRTE_DATEIEN = [ + "/CLAUDE.md", "/DEPLOY.md", "/wrangler.toml", "/netlify.toml", + "/gate-worker.js", "/_headers", "/.gitignore", "/.nojekyll", "/.assetsignore", +]; +app.use((req, res, next) => { + const pfad = req.path; + const hatVerstecktenOrdner = pfad + .split("/") + .some((teil) => teil.startsWith(".") && teil.length > 1 && teil !== ".well-known"); + const inGesperrtemOrdner = GESPERRTE_ORDNER.some((p) => pfad === p || pfad.startsWith(p + "/")); + const istGesperrteDatei = GESPERRTE_DATEIEN.includes(pfad); + const istBackupDatei = /\.bak(-|\.|$)/i.test(pfad); + if (hatVerstecktenOrdner || inGesperrtemOrdner || istGesperrteDatei || istBackupDatei) { + return res.status(404).sendFile(join(SITE_DIR, "404.html"), (err) => { + if (err) res.status(404).send("Nicht gefunden."); + }); + } + next(); +}); + app.use(express.static(SITE_DIR, { index: "index.html" })); app.use((req, res) => {