From 63dfd8d56161a92bd73377bd21b8500faaebf928 Mon Sep 17 00:00:00 2001 From: leemour Date: Thu, 15 Oct 2026 03:47:43 +0200 Subject: [PATCH] chore(lint): adopt the shared security lint rules Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: leemour --- biome.json | 2 +- config/wirecat/biome.base.json | 47 +++++++++++++++++++++++ config/wirecat/manifest.json | 8 +++- config/wirecat/no-exec-interpolation.grit | 17 ++++++++ config/wirecat/no-new-function.grit | 8 ++++ config/wirecat/no-shell-true.grit | 8 ++++ config/wirecat/no-unbounded-spread.grit | 10 +++++ performance/tasks/duplicates/evaluate.mjs | 1 + 8 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 config/wirecat/no-exec-interpolation.grit create mode 100644 config/wirecat/no-new-function.grit create mode 100644 config/wirecat/no-shell-true.grit create mode 100644 config/wirecat/no-unbounded-spread.grit diff --git a/biome.json b/biome.json index 102838a..c3006ef 100644 --- a/biome.json +++ b/biome.json @@ -8,7 +8,7 @@ "!**/node_modules", "!pnpm-lock.yaml", "!.claude/settings.json", - "!**/.worktrees", + "!.worktrees", "!config/wirecat", "!performance/documents/html-readers/fixtures", "!performance/documents/html-readers/reference", diff --git a/config/wirecat/biome.base.json b/config/wirecat/biome.base.json index b96a6de..438b2ab 100644 --- a/config/wirecat/biome.base.json +++ b/config/wirecat/biome.base.json @@ -38,6 +38,14 @@ "allow": ["error"] } } + }, + "security": { + "noSecrets": { + "level": "error", + "options": { + "entropyThreshold": 50 + } + } } } }, @@ -51,6 +59,45 @@ } } } + }, + { + "includes": [ + "**/*.test.*", + "**/*.spec.*", + "**/test/**", + "**/tests/**", + "**/__tests__/**", + "**/fixtures/**", + "**/generated/**" + ], + "linter": { + "rules": { + "security": { + "noSecrets": "off" + } + } + } + } + ], + "plugins": [ + "./config/wirecat/no-new-function.grit", + "./config/wirecat/no-shell-true.grit", + "./config/wirecat/no-exec-interpolation.grit", + { + "path": "./config/wirecat/no-unbounded-spread.grit", + "includes": [ + "**", + "!**/*.test.*", + "!**/*.spec.*", + "!**/test/**", + "!**/tests/**", + "!**/__tests__/**", + "!**/fixtures/**", + "!**/testing/**", + "!**/scripts/**", + "!**/bench/**", + "!**/performance/**" + ] } ] } diff --git a/config/wirecat/manifest.json b/config/wirecat/manifest.json index 23a7783..e7a821f 100644 --- a/config/wirecat/manifest.json +++ b/config/wirecat/manifest.json @@ -1,11 +1,15 @@ { "source": "https://github.com/WireCatLabs/community", - "revision": "5d00ac9d7e80eeedb4ec4c3c6748ad2ccf2af657", + "revision": "60a8857c04548e135f672db64e0723dbe87b433f", "files": { - "biome.base.json": "83a43910f2530e21d720e3ad4c3fc7fcb16ba36253c6dbc720b3c68a4dd80893", + "biome.base.json": "6a5a2efe0b8989c29458f47f79c35cf756e6277a6b51699fe832b0da49d67370", "cspell.json": "8241122ed4d461976a838099b265ef8f2689a066608257b6fdc250d9b49b58aa", "lefthook.yml": "2f65a2e3103006d43f6d6f0a07ab333c132286157763222a59a5a22676acd391", "markdownlint.json": "5ed7d6980054c539f3f3c0e47a090f1a725b15be2c486a769a836bc6cd48ad2d", + "no-exec-interpolation.grit": "b9461f887afd0f7d555814bc45c5cd47537808edc10a17b06049f3ca0fff5957", + "no-new-function.grit": "f6423e186cca90b1ab87d40185c6d920e99d83366af6dc11455963a0797fb627", + "no-shell-true.grit": "d3943cfa1d7ebbf7be0fa22c2aaf2b7d7aa9ff462f2eb14a7798632764e3875c", + "no-unbounded-spread.grit": "f4178e5b74212fef58fec8916b6783d9f4f192ac618aa4ced041c4167bfbf81b", "rumdl.toml": "048b929176f13234324f5825d1e811397f1491b9cb6684a1953e268e2c2ed863", "check.mjs": "34b266411eaab7707030915f645308e86784b1574b21fa44ca974861a90c9ce1" }, diff --git a/config/wirecat/no-exec-interpolation.grit b/config/wirecat/no-exec-interpolation.grit new file mode 100644 index 0000000..dc160b3 --- /dev/null +++ b/config/wirecat/no-exec-interpolation.grit @@ -0,0 +1,17 @@ +language js + +or { + `exec($args)`, + `execSync($args)`, + `$_.execSync($args)`, + `child_process.exec($args)`, + `childProcess.exec($args)`, + `cp.exec($args)` +} where { + $args <: [$command, ...], + $command <: or { + r"^`[\s\S]*\$\{[\s\S]*`$", + `$left + $right` + }, + register_diagnostic(span=$command, message="A command string built from values runs through a shell. Use execFile or spawn with an argument array.", severity="error") +} diff --git a/config/wirecat/no-new-function.grit b/config/wirecat/no-new-function.grit new file mode 100644 index 0000000..53d5be1 --- /dev/null +++ b/config/wirecat/no-new-function.grit @@ -0,0 +1,8 @@ +language js + +or { + `new Function($args)`, + `Function($args)` +} as $call where { + register_diagnostic(span=$call, message="Function() compiles a string into code, like eval. Pass a function value instead.", severity="error") +} diff --git a/config/wirecat/no-shell-true.grit b/config/wirecat/no-shell-true.grit new file mode 100644 index 0000000..8252cd7 --- /dev/null +++ b/config/wirecat/no-shell-true.grit @@ -0,0 +1,8 @@ +language js + +`shell: true` as $option where { + $option <: within `$callee($args)` where { + $callee <: r"^(?:.*\.)?(?:spawn|spawnSync|exec|execSync|execFile|execFileSync|fork)$" + }, + register_diagnostic(span=$option, message="shell: true hands the arguments to a shell, so a space, quote or ; in user data runs as a command. Call the program directly with an argument array.", severity="error") +} diff --git a/config/wirecat/no-unbounded-spread.grit b/config/wirecat/no-unbounded-spread.grit new file mode 100644 index 0000000..d034bcd --- /dev/null +++ b/config/wirecat/no-unbounded-spread.grit @@ -0,0 +1,10 @@ +language js + +or { + `$target.push($args)`, + `Math.max($args)`, + `Math.min($args)` +} as $call where { + $args <: some `...$items`, + register_diagnostic(span=$call, message="Spreading a list into call arguments throws past about 125,000 items. Loop or reduce instead.", severity="warn") +} diff --git a/performance/tasks/duplicates/evaluate.mjs b/performance/tasks/duplicates/evaluate.mjs index 21b3900..2b817d0 100644 --- a/performance/tasks/duplicates/evaluate.mjs +++ b/performance/tasks/duplicates/evaluate.mjs @@ -10,6 +10,7 @@ import { fileURLToPath, pathToFileURL } from "node:url" const here = dirname(fileURLToPath(import.meta.url)) const CORE_VERSION = "0.277.0" +// biome-ignore lint/security/noSecrets: published package integrity hash, not a key const CORE_INTEGRITY = "sha512-X0IBZ2waGP3EV4R5mbUnpT+nUFjXvPXvkwAS2lK3yeUfWVbazIVp1kJz1G2fKwsN7ZQH5dvW7zroeGWhyTk+Vg==" const DAY = 86_400_000 const SPLIT_SEED = "tasks-duplicates-1"