- make quick/check/mutation from cj/security-baseline (Makefile unchanged, settings in baseline.mk), pre-commit, gitleaks, Semgrep rules, ESLint security rules, Forgejo workflow - tests/security: generic baseline tests plus app config and role tests against createApp() with an in-memory database - extract createApp() from src/server/index.ts; LB_DATABASE_PATH for tests - fix gaps found by the tests: reject unknown fields on project create, answer malformed JSON with 400 instead of 500, set nosniff on the API - npm audit fix (next 16.4.1 and others, no high/critical left) - clear ESLint errors, safeFileName without control-character regex - per-project ownership stays an open, documented gap (idorGap -> TODO) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
3 KiB
JavaScript
82 lines
3 KiB
JavaScript
// ESLint-Sicherheitsregeln der Test- & Security-Baseline (Flat Config, ESLint 9.22+; ESLint 10
|
|
// scheitert Stand 10/2026 an der Peer-Dependency von eslint-plugin-react).
|
|
// Die Blöcke bis einschließlich der Sicherheitsregeln stammen aus der Baseline; die
|
|
// App-spezifischen Ergänzungen stehen darunter und sind einzeln begründet.
|
|
import js from "@eslint/js";
|
|
import { defineConfig } from "eslint/config";
|
|
import noUnsanitized from "eslint-plugin-no-unsanitized";
|
|
import react from "eslint-plugin-react";
|
|
import reactHooks from "eslint-plugin-react-hooks";
|
|
import security from "eslint-plugin-security";
|
|
import globals from "globals";
|
|
import tseslint from "typescript-eslint";
|
|
|
|
export default defineConfig(
|
|
{
|
|
ignores: [
|
|
"dist/**",
|
|
".next/**",
|
|
"node_modules/**",
|
|
"coverage/**",
|
|
"playwright-report/**",
|
|
// Lokale Artefakte der Baseline bzw. der App, nicht versioniert.
|
|
"reports/**",
|
|
"mutants/**",
|
|
".venv-tools/**",
|
|
"data/**",
|
|
"next-env.d.ts",
|
|
],
|
|
},
|
|
js.configs.recommended,
|
|
tseslint.configs.recommended,
|
|
security.configs.recommended,
|
|
noUnsanitized.configs.recommended,
|
|
{
|
|
files: ["**/*.{js,jsx,mjs,ts,tsx}"],
|
|
plugins: { react },
|
|
languageOptions: {
|
|
globals: { ...globals.browser, ...globals.node },
|
|
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
},
|
|
settings: { react: { version: "detect" } },
|
|
rules: {
|
|
// XSS
|
|
"react/no-danger": "error",
|
|
"react/no-danger-with-children": "error",
|
|
"react/jsx-no-script-url": "error",
|
|
"react/jsx-no-target-blank": "error",
|
|
// Code aus Strings
|
|
"no-eval": "error",
|
|
"no-implied-eval": "error",
|
|
"no-new-func": "error",
|
|
// Steuerzeichen in Regex: nicht abschalten, sondern Zeichencodes per Schleife prüfen.
|
|
"no-control-regex": "error",
|
|
// obj[key] meldet fast jede Zeile; IDOR/Prototype-Pollution fangen Tests und Review.
|
|
"security/detect-object-injection": "off",
|
|
},
|
|
},
|
|
|
|
// --- App-spezifisch (Leistungsbilanz) ---
|
|
{
|
|
files: ["**/*.{ts,tsx}"],
|
|
plugins: { "react-hooks": reactHooks },
|
|
rules: {
|
|
// Hook-Regeln für die Next.js-Oberfläche; der Code nutzt sie bereits per Kommentar.
|
|
"react-hooks/rules-of-hooks": "error",
|
|
"react-hooks/exhaustive-deps": "warn",
|
|
// Express verlangt für Fehler-Middleware vier Parameter; ungenutzte heißen _next usw.
|
|
"@typescript-eslint/no-unused-vars": [
|
|
"error",
|
|
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" },
|
|
],
|
|
// `declare global { namespace Express { ... } }` ist der dokumentierte Weg, Request zu erweitern.
|
|
"@typescript-eslint/no-namespace": ["error", { allowDeclarations: true }],
|
|
},
|
|
},
|
|
{
|
|
// Betriebs-Skripte in scripts/*.js sind CommonJS (laufen im Container ohne Build-Schritt).
|
|
files: ["scripts/**/*.js"],
|
|
languageOptions: { sourceType: "commonjs" },
|
|
rules: { "@typescript-eslint/no-require-imports": "off" },
|
|
},
|
|
);
|