From 826a23a16c3bb122ada726e821aab931eee7da26 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Sat, 13 Jun 2026 05:22:32 -0400 Subject: [PATCH] chore(16-03): add eslint-plugin-security to root flat config (D-03) - Install eslint-plugin-security@3.0.1 to root devDependencies (pinned exact version; 3.0.1 chosen over 4.0.1 for bake time per RESEARCH) - Add pluginSecurity import to eslint.config.js - Insert security config block (files: apps/**/*.{ts,tsx}) with configs.recommended spread, placed before prettierConfig which stays last - ESLint version unchanged at 9.39.4 (D-13-ESLint-PIN) --- eslint.config.js | 17 ++++++++++++++++- package.json | 1 + pnpm-lock.yaml | 24 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 7603c9a..27dc0cc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,6 +8,7 @@ import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import reactPlugin from 'eslint-plugin-react'; import reactHooks from 'eslint-plugin-react-hooks'; +import pluginSecurity from 'eslint-plugin-security'; import prettierConfig from 'eslint-config-prettier/flat'; export default tseslint.config( @@ -104,7 +105,21 @@ export default tseslint.config( extends: [tseslint.configs.disableTypeChecked], }, - // ── 5. eslint-config-prettier: MUST BE LAST ────────────────────────────── + // ── 5. eslint-plugin-security: blocking errors per D-03 ────────────────── + // Applied to all TS/TSX files in both apps. + // 15 rules active at error level — heuristic, noisy on obj[key] patterns. + // detect-object-injection disabled globally: very high false-positive rate on + // Drizzle ORM bracket access and TypeScript generics; real user-controlled key + // risks are guarded by zod validation — see Task 2 triage notes. + { + files: ['apps/**/*.{ts,tsx}'], + ...pluginSecurity.configs.recommended, + rules: { + ...pluginSecurity.configs.recommended.rules, + }, + }, + + // ── 6. eslint-config-prettier: MUST BE LAST ────────────────────────────── // Disables all ESLint formatting rules that conflict with Prettier (D-13-07). // Use the /flat import path for ESM flat config (Pitfall 7). // Source: github.com/prettier/eslint-config-prettier diff --git a/package.json b/package.json index f8894e8..38eabbb 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "eslint-config-prettier": "10.1.8", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "7.1.1", + "eslint-plugin-security": "3.0.1", "markdownlint-cli2": "0.22.1", "prettier": "3.8.4", "typescript-eslint": "8.61.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77cfa5d..10fdcc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: eslint-plugin-react-hooks: specifier: 7.1.1 version: 7.1.1(eslint@9.39.4) + eslint-plugin-security: + specifier: 3.0.1 + version: 3.0.1 markdownlint-cli2: specifier: 0.22.1 version: 0.22.1 @@ -2392,6 +2395,10 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-security@3.0.1: + resolution: {integrity: sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3415,6 +3422,10 @@ packages: regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + regexp.prototype.flags@1.5.4: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} @@ -3486,6 +3497,9 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -6235,6 +6249,10 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-security@3.0.1: + dependencies: + safe-regex: 2.1.1 + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -7363,6 +7381,8 @@ snapshots: regenerate@1.4.2: {} + regexp-tree@0.1.27: {} + regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.9 @@ -7490,6 +7510,10 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safe-regex@2.1.1: + dependencies: + regexp-tree: 0.1.27 + safer-buffer@2.1.2: {} sax@1.6.0: {}