eslint-plugin-ai-guard 1.4.5 → 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,8 +42,18 @@
42
42
  - **Hooks for Claude Code, Cursor and Codex** (`ai-guard init-hooks`): findings go back to the agent as it works, and it is stopped once before finishing on weakened checks or problems it introduced
43
43
  - **A pre-commit gate** (`ai-guard init-git-hook`) that checks every commit, whichever agent or person wrote it
44
44
  - **Works with Oxlint** as a JS plugin, with identical results checked in CI (`ai-guard init-oxlint`)
45
+ - **Package checks** (`ai-guard verify-deps`, an opt-in pre-install hook, and the `ai_guard_check_package` MCP tool): names that do not exist on npm, typosquats and npm security placeholders are blocked; install scripts, deprecations and releases from the last day are flagged
45
46
  - **MCP server** (`ai-guard-mcp`, 9 tools) for local AI-agent workflows over STDIO
46
47
 
48
+ ### Results on real projects
49
+
50
+ Measured on 12 November 2026 with 1.4.6. Methods, raw numbers and the commands to reproduce them: [docs/evidence.md](./docs/evidence.md).
51
+
52
+ - **0 of 1,361** real dependencies blocked (763 from 15 large open-source projects, 598 from 9 apps)
53
+ - **34 of 36** names from the 2017 crossenv malware campaign blocked
54
+ - **3.0%** of the 5,000 most-downloaded packages had a latest release under a day old, the window the fresh-release check covers
55
+ - **27 of 27** rules give identical results in ESLint and Oxlint, checked in CI
56
+
47
57
  It is engineered to detect reliability bugs, async hazards, security vulnerabilities, and code-scaffolding defects frequently introduced during AI-assisted development (GitHub Copilot, Cursor, Claude Code, Gemini Code Assist, etc.).
48
58
 
49
59
  AI Guard analyzes Abstract Syntax Trees (AST) using ESLint's native engine. It runs locally in your editor, in your terminal via the zero-config CLI, and in your CI/CD pipelines via native SARIF 2.1.0 integration with GitHub Code Scanning.
@@ -142,7 +152,7 @@ AI Guard includes **27 deterministic rules** divided into four specialized categ
142
152
 
143
153
  | Rule | Recommended | What It Catches | Fixable? |
144
154
  | :--- | :---: | :--- | :---: |
145
- | [`no-empty-catch`](./docs/rules/no-empty-catch.md) | **`error`** | Empty `catch (e) {}` blocks that silently swallow exceptions without logging or rethrowing. | **Yes** (inserts `/* TODO: handle error */`) |
155
+ | [`no-empty-catch`](./docs/rules/no-empty-catch.md) | **`error`** | Empty `catch (e) {}` blocks that silently swallow exceptions without logging or rethrowing. | No (editor suggestion: rethrow) |
146
156
  | [`no-broad-exception`](./docs/rules/no-broad-exception.md) | `warn` | Catching broad exception types like `catch (e: any)` that mask system faults and typing. | No |
147
157
  | [`no-catch-log-rethrow`](./docs/rules/no-catch-log-rethrow.md) | `off`* | Catch blocks that only log to `console` and rethrow without adding context or diagnostic info. | No |
148
158
  | [`no-catch-without-use`](./docs/rules/no-catch-without-use.md) | `off`* | Caught error variables that are declared in catch parameters but never referenced. | No |
@@ -152,7 +162,7 @@ AI Guard includes **27 deterministic rules** divided into four specialized categ
152
162
 
153
163
  | Rule | Recommended | What It Catches | Fixable? |
154
164
  | :--- | :---: | :--- | :---: |
155
- | [`no-floating-promise`](./docs/rules/no-floating-promise.md) | **`error`** | Async function invocations without `await`, `.catch()`, or `return` — leading to silent dropped errors. | **Yes** (marks with `void`) |
165
+ | [`no-floating-promise`](./docs/rules/no-floating-promise.md) | **`error`** | Async function invocations without `await`, `.catch()`, or `return` — leading to silent dropped errors. | No (editor suggestions: `await`, or `void` if intended) |
156
166
  | [`no-async-array-callback`](./docs/rules/no-async-array-callback.md) | `warn` | Async callbacks passed to `map()`, `filter()`, `forEach()`, or `reduce()` returning `Promise[]`. | No |
157
167
  | [`no-await-in-loop`](./docs/rules/no-await-in-loop.md) | `warn` | Sequential `await` in loops where iterations can be safely executed concurrently with `Promise.all`. | **Yes** (rewrites to `Promise.all`) |
158
168
  | [`no-async-without-await`](./docs/rules/no-async-without-await.md) | `warn` | Functions declared `async` that never execute an `await` expression, adding unnecessary Promise overhead. | No |
@@ -183,7 +193,7 @@ Linting checks the code. These check the agent:
183
193
  | [`ai-guard verify`](./docs/cli/verify.md) | One verdict for the current change: lint findings it introduced, weakened tests, and agent-config issues. Pre-existing problems never block. |
184
194
  | [`ai-guard integrity`](./docs/integrity.md) | Everything that weakens checks vs a base revision: new suppressions, skipped or removed tests, lowered coverage and TypeScript settings, removed CI steps. |
185
195
  | [`ai-guard changed --test-integrity`](./docs/cli/test-integrity.md) | A test-focused comparison: focused, skipped, removed or weakened tests, rewritten snapshots, and test commands that can no longer fail. Overlaps with `integrity`; use `integrity` for the full set. |
186
- | [`ai-guard verify-deps`](./docs/cli/verify-deps.md) | Checks npm packages before they are installed: names that don't exist (invented by assistants), look-alikes of popular packages, new or rarely used packages, install scripts, deprecations. Also as a pre-install hook for Claude Code, Cursor and Codex (`init-hooks --check-installs`) and the `ai_guard_check_package` MCP tool. Uses the npm registry; private registries are skipped. |
196
+ | [`ai-guard verify-deps`](./docs/cli/verify-deps.md) | Checks npm packages before they are installed: names that don't exist (invented by assistants), look-alikes of popular packages, new or rarely used packages, install scripts, deprecations, and releases published in the last day (skipped when the package manager enforces a release cooldown). Also as a pre-install hook for Claude Code, Cursor and Codex (`init-hooks --check-installs`) and the `ai_guard_check_package` MCP tool. Uses the npm registry; private registries are skipped. |
187
197
  | [`ai-guard scan-agent-config`](./docs/cli/scan-agent-config.md) | Scans `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, skills and MCP configs for hidden text, prompt injection, unpinned MCP servers and inline secrets. |
188
198
  | [Agent hooks: Claude Code, Cursor, Codex](./docs/integrations/agents.md) | `ai-guard init-hooks` sets up every agent a project uses. Findings reach the agent after edits; before it finishes, the whole change is verified once; `git commit --no-verify` and risky installs are caught before they run. |
189
199
  | [Pre-commit gate](./docs/integrations/git-hook.md) | `ai-guard init-git-hook` runs `verify --staged` on every commit through husky, lefthook, simple-git-hooks or pre-commit. Only problems the commit introduces block it. |
@@ -402,7 +412,7 @@ npx ai-guard init-claude
402
412
 
403
413
  - **PostToolUse** — after each edit, findings from the `agent` preset and newly weakened checks in the edited file are sent back to Claude (`decision: "block"` + `reason`, per the hooks protocol). Earlier versions printed plain stdout, which Claude Code does not show to Claude.
404
414
  - **SessionStart + Stop** — before Claude finishes, [check integrity](./docs/integrity.md) runs on everything changed in the session. High-confidence weakenings (a new `.skip`, `eslint-disable`, lowered threshold…) block stopping once per finding set; advisories are shown to you, never block. The same hook then [verifies](./docs/cli/verify.md) lint findings and agent-config issues the session introduced (placeholder code, a canned return under a test runner, a hidden instruction in `CLAUDE.md`), which also block once. Skip both with `--no-stop-hook`.
405
- - **PreToolUse (Bash)** — `git commit --no-verify` / `HUSKY=0` ask for confirmation. With `--check-installs` (opt-in, uses the npm registry), packages in install commands are checked first: names that don't exist are blocked, look-alikes of popular packages ask you.
415
+ - **PreToolUse (Bash)** — `git commit --no-verify` / `HUSKY=0` ask for confirmation. With `--check-installs` (opt-in, uses the npm registry), packages in install commands are checked first: names that don't exist are blocked; look-alikes of popular packages and releases from the last day ask you.
406
416
 
407
417
  ```bash
408
418
  # Preview before applying
@@ -455,14 +465,25 @@ jobs:
455
465
  cache: 'npm'
456
466
 
457
467
  - name: Run AI Guard
468
+ id: aiguard
458
469
  uses: ai-guard-dev/eslint-plugin-ai-guard@v1
459
470
  with:
460
471
  preset: 'recommended'
461
472
  fail-on: 'high'
462
473
  changed-only: 'true'
463
- upload-sarif: 'true'
474
+
475
+ # The Action writes SARIF; this step sends it to Code Scanning.
476
+ # if: always() uploads it even when the scan step fails the job.
477
+ - name: Upload to GitHub Code Scanning
478
+ if: always()
479
+ uses: github/codeql-action/upload-sarif@v3
480
+ with:
481
+ sarif_file: ${{ steps.aiguard.outputs.sarif-file }}
482
+ category: ai-guard
464
483
  ```
465
484
 
485
+ The Action annotates the pull request and writes the job summary by itself. Alerts in **Security → Code scanning** need the upload step.
486
+
466
487
  ### Action Inputs (`action.yml`)
467
488
 
468
489
  | Input | Description | Default |
@@ -471,7 +492,7 @@ jobs:
471
492
  | `fail-on` | Severity threshold to fail CI: `high` \| `medium` \| `any` \| `none` | `'high'` |
472
493
  | `changed-only` | Scan only files changed in this PR / commit | `'true'` |
473
494
  | `path` | Target file or directory to scan | `'.'` |
474
- | `upload-sarif` | Upload results to GitHub Code Scanning | `'true'` |
495
+ | `upload-sarif` | Always write the SARIF file (`sarif-file` output) for an `upload-sarif` step, even when the scan produced none. The Action does not upload to Code Scanning by itself | `'true'` |
475
496
  | `github-summary` | Write an execution breakdown to the GitHub Actions Job Summary | `'true'` |
476
497
  | `working-directory`| Working directory for scanning (ideal for monorepos) | `'.'` |
477
498
  | `package-manager` | Package manager: `auto` \| `npm` \| `pnpm` \| `yarn` | `'auto'` |
@@ -610,10 +631,10 @@ npx eslint . --fix
610
631
  | Rule | Automatic Fix Behavior |
611
632
  | :--- | :--- |
612
633
  | `no-hardcoded-secret` | Replaces hardcoded string literal with `process.env.VARIABLE_NAME` |
613
- | `no-empty-catch` | Inserts `/* TODO: handle error */` comment to prevent silent swallowing |
614
- | `no-floating-promise` | Prepends `void ` expression to intentionally unawaited calls |
615
634
  | `no-await-in-loop` | Rewrites straightforward sequential loops to `await Promise.all(...)` |
616
635
 
636
+ `no-empty-catch` and `no-floating-promise` have no automatic fix on purpose. A fix that inserted a comment or `void` would make the finding disappear without handling the error, and an agent running `--fix` would do exactly that. Editors offer them as suggestions instead (rethrow; `await`, or `void` for an intended fire-and-forget call), which a person applies one at a time.
637
+
617
638
  ---
618
639
 
619
640
  ## Benchmarks & Empirical Evaluation
@@ -712,7 +733,7 @@ npx --yes --package eslint-plugin-ai-guard ai-guard-mcp
712
733
  | :--- | :--- |
713
734
  | `ai_guard_scan_file` | Scan a single JS/TS file with structured findings |
714
735
  | `ai_guard_scan_diff` | Scan changed files in git diff (including newly created untracked JS/TS files) |
715
- | `ai_guard_scan_project` | Scan a bounded workspace directory (current source; not yet published) |
736
+ | `ai_guard_scan_project` | Scan a bounded workspace directory (at most 500 files; fails instead of truncating) |
716
737
  | `ai_guard_rules` | List rules and presets, or look up specific rules (`rules: ["no-floating-promise"]`) with remediation and docs link |
717
738
  | `ai_guard_check_integrity` | Report checks weakened by current Git changes (new suppressions, skipped/removed tests, lowered configs, removed CI steps), with `tier` and `hasBlockingFindings` |
718
739