eslint-plugin-vercel-ai-security 1.3.8 → 1.3.10

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/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ ## 1.3.10
2
+
3
+ ### Patch Changes
4
+
5
+ - [#294](https://github.com/ofri-peretz/eslint/pull/294) [`659f6dc`](https://github.com/ofri-peretz/eslint/commit/659f6dc0181b03b675f72b5949fcf123dd066358) Thanks [@ofri-peretz](https://github.com/ofri-peretz)! - Rewrite `description` and `keywords` on every published package for npm search discovery. npm ranks on name, description, and keywords, and the registry only picks up these fields at publish — so this is metadata-only and takes effect for each package on its next release.
6
+
7
+ **Descriptions now lead with the search phrase.** Every one starts `ESLint plugin for <the thing you'd search>` instead of a brand-first or category-first framing, and names the concrete vulnerabilities the plugin actually detects. Three were corrected while doing so:
8
+
9
+ - `eslint-plugin-import-next` claimed "100x faster no-cycle detection". No 100x measurement exists: `CLAIMS.md` records **3.1x end-to-end** (8x in pure rule execution) on a 5,483-file React codebase, and the highest number in any benchmark result is 54.9x on the synthetic corpus. The description now states the real-codebase figure.
10
+ - `eslint-plugin-secure-coding` claimed SQL injection, XSS and CSRF coverage — none of which are its rules. It now names what it does detect: LDAP, XPath, XXE, GraphQL and template injection, unsafe deserialization, ReDoS, missing authentication, and PII in logs.
11
+ - `eslint-plugin-secure-coding` ("89 rules") and `eslint-plugin-react-a11y` ("37 rules") hard-coded rule counts that had drifted from reality. Counts are generated into `interlace-numbers.json`; hand-typed copies are removed rather than corrected.
12
+
13
+ **Keywords now match the vocabulary of the plugins that rank.** `eslint-plugin-security`, `eslint-plugin-jsx-a11y`, `eslint-plugin-n` and `eslint-plugin-import` all carry the `eslint` / `eslintplugin` / `eslint-plugin` trio — six of our packages were missing `eslintplugin`, and every one now carries all three plus `static-analysis`, `linting` and `code-quality`. Security plugins add `sast`, `appsec` and `vulnerability`; `node-security` and `secure-coding` also carry `nodesecurity`, the exact keyword `eslint-plugin-security` ranks on. Each plugin gained the CWE identifiers and attack names for what it detects (`cwe-78` command injection, `cwe-22` path traversal, `cwe-89` SQL injection, `cwe-79` XSS, `cwe-347` JWT algorithm confusion, `cwe-352` CSRF, `cwe-943` NoSQL injection), and `node-security` gained the crypto vocabulary it had been missing entirely despite absorbing the crypto rule set (`crypto`, `cryptography`, `weak-hash`, `md5`, `sha1`, `timing-attack`).
14
+
15
+ No rule behavior, exports, or configuration changes.
16
+
17
+ - Updated dependencies [[`e1cdf83`](https://github.com/ofri-peretz/eslint/commit/e1cdf83e3db761907f0ab06f7fc6c1f1da7513a5), [`659f6dc`](https://github.com/ofri-peretz/eslint/commit/659f6dc0181b03b675f72b5949fcf123dd066358)]:
18
+ - @interlace/eslint-devkit@1.4.3
19
+
20
+ ## 1.3.9
21
+
22
+ ### Patch Changes
23
+
24
+ - [#277](https://github.com/ofri-peretz/eslint/pull/277) [`d1ad332`](https://github.com/ofri-peretz/eslint/commit/d1ad332cc7366887482b288bcf65098d425501d0) Thanks [@ofri-peretz](https://github.com/ofri-peretz)! - Accept AI SDK v5+ idioms: `stopWhen` (e.g. `stopWhen: stepCountIs(5)`) now satisfies require-max-steps, and `maxOutputTokens` (v5 rename of `maxTokens`) satisfies require-max-tokens — fixing false positives on v5/v7 code.
25
+
1
26
  ## 1.3.8
2
27
 
3
28
  ### Patch Changes
package/README.md CHANGED
@@ -136,8 +136,8 @@ See the [ESLint Version Support Policy](../../docs/ESLINT_VERSION_SUPPORT.md) fo
136
136
  | [require-audit-logging](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-audit-logging?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-778 | | | This rule identifies AI SDK calls that aren't preceded by logging statements | 🟢 | | | | | |
137
137
  | [require-embedding-validation](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-embedding-validation?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-20 | | | This rule identifies code patterns where embeddings are stored in vector databases without validation. | 🟢 | | | | | |
138
138
  | [require-error-handling](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-error-handling?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-755 | | | This rule identifies AI SDK calls that aren't wrapped in try-catch blocks | 🟢 | | | | | |
139
- | [require-max-steps](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-max-steps?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-834 | | | This rule identifies AI SDK calls that use tools but don't specify a maxSteps limit | 🟢 | | | | | |
140
- | [require-max-tokens](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-max-tokens?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-770 | | | This rule identifies AI SDK calls that don't specify a maxTokens limit | 🟢 | | | | | |
139
+ | [require-max-steps](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-max-steps?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-834 | | | This rule identifies AI SDK calls that use tools but don't specify a step limit (maxSteps or stopWhen) | 🟢 | | | | | |
140
+ | [require-max-tokens](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-max-tokens?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-770 | | | This rule identifies AI SDK calls that don't specify a token limit (maxTokens or maxOutputTokens) | 🟢 | | | | | |
141
141
  | [require-output-filtering](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-output-filtering?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-200 | | | This rule identifies tool execute functions that return raw data from data sources (databases, APIs, file s… | 🟢 | | | | | |
142
142
  | [require-output-validation](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-output-validation?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-707 | | | This rule identifies code patterns where AI-generated output is displayed to users without validation or fa… | 🟢 | | | | | |
143
143
  | [require-rag-content-validation](https://eslint.interlace.tools/docs/security/plugin-vercel-ai-security/rules/require-rag-content-validation?utm_source=github&utm_medium=referral&utm_campaign=eslint-plugin-vercel-ai-security) | CWE-74 | | | This rule identifies code patterns where content retrieved from vector stores or document retrieval systems… | 🟢 | | | | | |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-vercel-ai-security",
3
- "version": "1.3.8",
4
- "description": "Security-focused ESLint plugin for Vercel AI SDK. SDK-aware rules for generateText, streamText, tools, and streaming patterns with full type knowledge.",
3
+ "version": "1.3.10",
4
+ "description": "ESLint plugin for Vercel AI SDK security — detects prompt injection, system-prompt leaks, hardcoded API keys, and unvalidated model output in generateText and streamText.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
7
7
  "types": "./src/index.d.ts",
@@ -43,27 +43,35 @@
43
43
  ],
44
44
  "keywords": [
45
45
  "eslint",
46
- "eslint-plugin",
47
46
  "eslintplugin",
48
- "interlace-security",
47
+ "eslint-plugin",
48
+ "static-analysis",
49
+ "linting",
50
+ "code-quality",
49
51
  "security",
52
+ "sast",
53
+ "appsec",
54
+ "vulnerability",
55
+ "owasp",
56
+ "cwe",
57
+ "interlace-security",
50
58
  "vercel",
51
59
  "vercel-ai",
60
+ "vercel-ai-sdk",
52
61
  "ai-sdk",
53
- "generateText",
54
- "streamText",
62
+ "ai-security",
55
63
  "llm",
64
+ "llm-security",
65
+ "generative-ai",
56
66
  "prompt-injection",
57
- "owasp",
58
67
  "owasp-llm-top-10",
59
- "cwe",
60
- "vulnerability",
68
+ "rag",
69
+ "tool-calling",
70
+ "generateText",
71
+ "streamText",
61
72
  "llm-optimized",
62
73
  "ai-assistant",
63
- "typescript",
64
- "linting",
65
- "code-quality",
66
- "static-analysis"
74
+ "typescript"
67
75
  ],
68
76
  "engines": {
69
77
  "node": ">=18.0.0"
@@ -78,7 +86,7 @@
78
86
  },
79
87
  "dependencies": {
80
88
  "tslib": "^2.3.0",
81
- "@interlace/eslint-devkit": "^1.4.2"
89
+ "@interlace/eslint-devkit": "^1.4.3"
82
90
  },
83
91
  "devDependencies": {
84
92
  "@ai-sdk/openai": "^4.0.16",
package/src/index.js CHANGED
@@ -152,7 +152,7 @@ exports.rules = {
152
152
  exports.plugin = {
153
153
  meta: {
154
154
  name: 'eslint-plugin-vercel-ai-security',
155
- version: '1.3.8',
155
+ version: '1.3.10',
156
156
  },
157
157
  rules: exports.rules,
158
158
  };
@@ -30,10 +30,10 @@ exports.requireMaxSteps = (0, eslint_devkit_1.createRule)({
30
30
  cwe: 'CWE-834',
31
31
  owasp: 'A05:2021',
32
32
  cvss: 6.5,
33
- description: '{{function}} with tools is missing maxSteps. Without a limit, tool calls can loop indefinitely.',
33
+ description: '{{function}} with tools is missing a step limit. Without a limit, tool calls can loop indefinitely.',
34
34
  severity: 'MEDIUM',
35
35
  compliance: ['SOC2'],
36
- fix: 'Add maxSteps option: {{function}}({ ..., maxSteps: 5 })',
36
+ fix: 'Add a step limit: {{function}}({ ..., stopWhen: stepCountIs(5) }) (v5+) or maxSteps: 5 (v4)',
37
37
  documentationLink: 'https://sdk.vercel.ai/docs/ai-sdk-core/tools-and-tool-calling#multi-step-calls-using-stopwhen',
38
38
  }),
39
39
  },
@@ -81,7 +81,7 @@ exports.requireMaxSteps = (0, eslint_devkit_1.createRule)({
81
81
  // Only check for maxSteps if tools are present
82
82
  if (!hasTools)
83
83
  return;
84
- // Check if maxSteps is present
84
+ // Check if a step limit is present: maxSteps (v4) or stopWhen (v5+, e.g. stopWhen: stepCountIs(5))
85
85
  const hasMaxSteps = optionsArg.properties.some(prop => {
86
86
  if (prop.type !== 'Property')
87
87
  return false;
@@ -90,7 +90,8 @@ exports.requireMaxSteps = (0, eslint_devkit_1.createRule)({
90
90
  : prop.key.type === 'Literal'
91
91
  ? String(prop.key.value)
92
92
  : null;
93
- return keyName === 'maxSteps' || keyName === 'max_steps';
93
+ // ponytail: any stopWhen counts — statically proving it bounds steps (arrays, custom conditions) isn't worth it; documented FN
94
+ return keyName === 'maxSteps' || keyName === 'max_steps' || keyName === 'stopWhen';
94
95
  });
95
96
  if (!hasMaxSteps) {
96
97
  context.report({
@@ -30,10 +30,10 @@ exports.requireMaxTokens = (0, eslint_devkit_1.createRule)({
30
30
  cwe: 'CWE-770',
31
31
  owasp: 'A05:2021',
32
32
  cvss: 6.5,
33
- description: '{{function}} call without maxTokens limit can lead to excessive resource consumption',
33
+ description: '{{function}} call without a token limit can lead to excessive resource consumption',
34
34
  severity: 'MEDIUM',
35
35
  compliance: ['SOC2'],
36
- fix: 'Add maxTokens option: {{function}}({ maxTokens: 4096, ... })',
36
+ fix: 'Add a token limit: {{function}}({ maxOutputTokens: 4096, ... }) (v5+) or maxTokens (v4)',
37
37
  documentationLink: 'https://sdk.vercel.ai/docs/ai-sdk-core/generating-text',
38
38
  }),
39
39
  },
@@ -81,7 +81,7 @@ exports.requireMaxTokens = (0, eslint_devkit_1.createRule)({
81
81
  if (!optionsArg || optionsArg.type !== 'ObjectExpression') {
82
82
  return;
83
83
  }
84
- // Check if maxTokens is present
84
+ // Check if a token limit is present: maxTokens (v4) or maxOutputTokens (v5+ rename)
85
85
  const hasMaxTokens = optionsArg.properties.some(prop => {
86
86
  if (prop.type !== 'Property')
87
87
  return false;
@@ -90,7 +90,7 @@ exports.requireMaxTokens = (0, eslint_devkit_1.createRule)({
90
90
  : prop.key.type === 'Literal'
91
91
  ? String(prop.key.value)
92
92
  : null;
93
- return keyName === 'maxTokens' || keyName === 'max_tokens';
93
+ return keyName === 'maxTokens' || keyName === 'max_tokens' || keyName === 'maxOutputTokens';
94
94
  });
95
95
  if (!hasMaxTokens) {
96
96
  context.report({