eslint-plugin-vercel-ai-security 1.2.0 โ†’ 1.3.0

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
@@ -1,116 +1,40 @@
1
- # eslint-plugin-vercel-ai-security
1
+ <p align="center">
2
+ <a href="https://eslint.interlace.tools" target="blank"><img src="https://eslint.interlace.tools/eslint-interlace-logo-light.svg" alt="ESLint Interlace Logo" width="120" /></a>
3
+ </p>
2
4
 
3
- <div align="center">
4
- <img src="https://eslint.interlace.tools/images/og-ai-security.png" alt="ESLint Interlace - eslint-plugin-vercel-ai-security" width="100%" />
5
- </div>
5
+ <p align="center">
6
+ Security rules for Vercel AI SDK usage (prompt injection, data handling).
7
+ </p>
6
8
 
7
- > ๐Ÿ”’ **The Definitive Security Plugin for Vercel AI SDK** โ€” Protect your AI applications from prompt injection, sensitive data leaks, and agentic vulnerabilities with **complete OWASP coverage**.
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/eslint-plugin-vercel-ai-security" target="_blank"><img src="https://img.shields.io/npm/v/eslint-plugin-vercel-ai-security.svg" alt="NPM Version" /></a>
11
+ <a href="https://www.npmjs.com/package/eslint-plugin-vercel-ai-security" target="_blank"><img src="https://img.shields.io/npm/dm/eslint-plugin-vercel-ai-security.svg" alt="NPM Downloads" /></a>
12
+ <a href="https://opensource.org/licenses/MIT" target="_blank"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="Package License" /></a>
13
+ <a href="https://app.codecov.io/gh/ofri-peretz/eslint/components?components%5B0%5D=vercel-ai-security" target="_blank"><img src="https://codecov.io/gh/ofri-peretz/eslint/graph/badge.svg?component=vercel-ai-security" alt="Codecov" /></a>
14
+ <a href="https://github.com/ofri-peretz/eslint" target="_blank"><img src="https://img.shields.io/badge/Since-Dec_2025-blue?logo=rocket&logoColor=white" alt="Since Dec 2025" /></a>
15
+ </p>
8
16
 
9
- **eslint-plugin-vercel-ai-security** is a specialized ESLint plugin that provides **SDK-aware security rules** for the [Vercel AI SDK](https://sdk.vercel.ai/). Unlike generic AI security linters, this plugin has **full knowledge** of the AI SDK's API structure, enabling precise detection of security vulnerabilities in `generateText`, `streamText`, `generateObject`, `streamObject`, and tool definitions.
17
+ ## Description
10
18
 
11
- [![npm version](https://badge.fury.io/js/eslint-plugin-vercel-ai-security.svg)](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security)
12
- [![npm downloads](https://img.shields.io/npm/dm/eslint-plugin-vercel-ai-security.svg)](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security)
13
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
- [![codecov](https://codecov.io/gh/ofri-peretz/eslint/graph/badge.svg?component=vercel_ai_security)](https://app.codecov.io/gh/ofri-peretz/eslint/components?components%5B0%5D=vercel_ai_security)
15
- [![OWASP LLM Coverage](https://img.shields.io/badge/OWASP%20LLM%202025-10%2F10-brightgreen)](https://owasp.org/www-project-top-10-for-large-language-model-applications/)
16
- [![OWASP Agentic Coverage](https://img.shields.io/badge/OWASP%20Agentic%202026-9%2F10-brightgreen)](https://owasp.org)
17
- [![Dec 2025](https://img.shields.io/badge/Dec_2025-blue?logo=rocket&logoColor=white)](https://github.com/ofri-peretz/eslint)
19
+ This plugin enforces security best practices for applications using the Vercel AI SDK, specifically targeting prompt injection and data handling vulnerabilities. It ensures that your AI integrations remain secure by validating inputs, outputs, and preventing common pitfalls associated with Large Language Models. By adopting these rules, you can confidently build AI-powered features while maintaining a robust security posture.
18
20
 
19
- ---
20
-
21
- ## ๐Ÿ’ก What you get
21
+ ## Philosophy
22
22
 
23
- - **SDK-aware detection:** Full knowledge of `generateText`, `streamText`, `generateObject`, `streamObject`, and tool definitions for precise vulnerability detection.
24
- - **LLM-optimized & MCP-ready:** Structured 2-line messages with CWE + OWASP + CVSS + concrete fixes so humans _and_ AI auto-fixers stay aligned.
25
- - **Complete OWASP coverage:** 100% of OWASP LLM Top 10 2025 + 90% of OWASP Agentic Top 10 2026.
26
- - **Tiered presets:** `recommended`, `strict`, `minimal` for fast policy rollout.
27
- - **Zero false positives:** SDK-specific detection eliminates generic pattern matching noise.
28
-
29
- ---
23
+ **Interlace** fosters **strength through integration**. Instead of stacking isolated rules, we **interlace** security directly into your workflow to create a resilient fabric of code. We believe tools should **guide rather than gatekeep**, providing educational feedback that strengthens the developer with every interaction.
30
24
 
31
- ## ๐Ÿ“Š OWASP Coverage Matrix
25
+ ## Getting Started
32
26
 
33
- | Framework | Coverage | Categories |
34
- | ----------------------------- | ------------ | ------------------------ |
35
- | **OWASP LLM Top 10 2025** | 10/10 (100%) | LLM01-LLM10 |
36
- | **OWASP Agentic Top 10 2026** | 9/10 (90%) | ASI01-ASI05, ASI07-ASI10 |
37
-
38
- > **Note:** ASI06 (Memory Corruption) is N/A for TypeScript/JavaScript as these are memory-safe languages.
39
-
40
- ---
41
-
42
- ## ๐Ÿ“ฆ Installation
27
+ - To check out the [guide](https://eslint.interlace.tools/docs/vercel-ai-security), visit [eslint.interlace.tools](https://eslint.interlace.tools). ๐Ÿ“š
28
+ - ่ฆๆŸฅ็œ‹ไธญๆ–‡ [ๆŒ‡ๅ—](https://eslint.interlace.tools/docs/vercel-ai-security), ่ฏท่ฎฟ้—ฎ [eslint.interlace.tools](https://eslint.interlace.tools). ๐Ÿ“š
29
+ - [๊ฐ€์ด๋“œ](https://eslint.interlace.tools/docs/vercel-ai-security) ๋ฌธ์„œ๋Š” [eslint.interlace.tools](https://eslint.interlace.tools)์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ“š
30
+ - [ใ‚ฌใ‚คใƒ‰](https://eslint.interlace.tools/docs/vercel-ai-security)ใฏ [eslint.interlace.tools](https://eslint.interlace.tools)ใงใ”็ขบ่ชใใ ใ•ใ„ใ€‚ ๐Ÿ“š
31
+ - Para ver la [guรญa](https://eslint.interlace.tools/docs/vercel-ai-security), visita [eslint.interlace.tools](https://eslint.interlace.tools). ๐Ÿ“š
32
+ - ู„ู„ุงุทู„ุงุน ุนู„ู‰ [ุงู„ุฏู„ูŠู„](https://eslint.interlace.tools/docs/vercel-ai-security)ุŒ ู‚ู… ุจุฒูŠุงุฑุฉ [eslint.interlace.tools](https://eslint.interlace.tools). ๐Ÿ“š
43
33
 
44
34
  ```bash
45
- # npm
46
35
  npm install eslint-plugin-vercel-ai-security --save-dev
47
-
48
- # pnpm
49
- pnpm add -D eslint-plugin-vercel-ai-security
50
-
51
- # yarn
52
- yarn add -D eslint-plugin-vercel-ai-security
53
- ```
54
-
55
- ---
56
-
57
- ## ๐Ÿš€ Quick Start
58
-
59
- ### ESLint Flat Config (Recommended)
60
-
61
- ```javascript
62
- // eslint.config.js
63
- import vercelAISecurity from 'eslint-plugin-vercel-ai-security';
64
-
65
- export default [vercelAISecurity.configs.recommended];
66
36
  ```
67
37
 
68
- ### Available Presets
69
-
70
- | Preset | Description |
71
- | ----------------- | ----------------------------------------------------------------------- |
72
- | **`recommended`** | Balanced security: Critical rules as errors, high-priority as warnings. |
73
- | **`strict`** | Maximum security: All rules enabled as errors for production. |
74
- | **`minimal`** | Gradual adoption: Only the 2 most critical rules. |
75
-
76
- ---
77
-
78
- ## ๐Ÿ“‹ Complete Rules Reference (19 Rules)
79
-
80
- ๐Ÿ’ผ = Set in `recommended` | โš ๏ธ = Warns in `recommended` | ๐Ÿ’ก = Suggestions
81
-
82
- ### ๐Ÿ›ก๏ธ OWASP LLM Top 10 2025 (10/10 โœ…)
83
-
84
- | Rule | CWE | OWASP | CVSS | Description | ๐Ÿ’ผ | โš ๏ธ | ๐Ÿ”ง | ๐Ÿ’ก | ๐Ÿšซ |
85
- | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: |
86
- | [require-validated-prompt](./docs/rules/require-validated-prompt.md) | CWE-74 | LLM01 | 9.0 | Prevent prompt injection via input validation | ๐Ÿ’ผ | | | | |
87
- | [no-sensitive-in-prompt](./docs/rules/no-sensitive-in-prompt.md) | CWE-200 | LLM02 | 8.0 | Prevent sensitive data (secrets, PII) in prompts | ๐Ÿ’ผ | | | | |
88
- | [no-training-data-exposure](./docs/rules/no-training-data-exposure.md) | CWE-359 | LLM03 | 7.0 | Prevent user data exposure to training endpoints | | โš ๏ธ | | | |
89
- | [require-request-timeout](./docs/rules/require-request-timeout.md) | CWE-400 | LLM04 | 5.0 | Require timeouts for AI calls to prevent DoS | | โš ๏ธ | | | |
90
- | [no-unsafe-output-handling](./docs/rules/no-unsafe-output-handling.md) | CWE-94 | LLM05 | 9.8 | Prevent unsafe use of AI output (eval, SQL, HTML) | ๐Ÿ’ผ | | | | |
91
- | [require-tool-confirmation](./docs/rules/require-tool-confirmation.md) | CWE-862 | LLM06 | 7.0 | Require confirmation for destructive tool usage | ๐Ÿ’ผ | | | | |
92
- | [no-system-prompt-leak](./docs/rules/no-system-prompt-leak.md) | CWE-200 | LLM07 | 7.5 | Prevent system prompt leakage in responses | ๐Ÿ’ผ | | | | |
93
- | [require-embedding-validation](./docs/rules/require-embedding-validation.md) | CWE-20 | LLM08 | 5.5 | Validate embeddings before storage/search | | | | ๐Ÿ’ก | |
94
- | [require-output-validation](./docs/rules/require-output-validation.md) | CWE-707 | LLM09 | 5.0 | Validate AI output before display to prevent misinformation | | | | ๐Ÿ’ก | |
95
- | [require-max-tokens](./docs/rules/require-max-tokens.md) | CWE-770 | LLM10 | 6.5 | Require `maxTokens` limit to prevent exhaustion | | โš ๏ธ | | | |
96
- | [require-max-steps](./docs/rules/require-max-steps.md) | CWE-834 | LLM10 | 6.5 | Require `maxSteps` for multi-step tools | | โš ๏ธ | | | |
97
- | [require-abort-signal](./docs/rules/require-abort-signal.md) | CWE-404 | LLM10 | 4.0 | Require `abortSignal` for cancellable streams | | | | ๐Ÿ’ก | |
98
- ### ๐Ÿค– OWASP Agentic Top 10 2026 (9/10 โœ…)
99
-
100
- | Rule | CWE | OWASP | CVSS | Description | ๐Ÿ’ผ | โš ๏ธ | ๐Ÿ”ง | ๐Ÿ’ก | ๐Ÿšซ |
101
- | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: |
102
- | [no-dynamic-system-prompt](./docs/rules/no-dynamic-system-prompt.md) | CWE-74 | ASI01 | 8.0 | Prevent dynamic system prompts (Agent Confusion) | ๐Ÿ’ผ | | | | |
103
- | [require-tool-schema](./docs/rules/require-tool-schema.md) | CWE-20 | ASI02 | 7.5 | Require Zod schemas for all tool parameters | | โš ๏ธ | | | |
104
- | [no-hardcoded-api-keys](./docs/rules/no-hardcoded-api-keys.md) | CWE-798 | ASI03 | 8.5 | Prevent hardcoded API keys in configuration | ๐Ÿ’ผ | | | | |
105
- | [require-output-filtering](./docs/rules/require-output-filtering.md) | CWE-200 | ASI04 | 6.5 | Filter sensitive data returned by tools | | โš ๏ธ | | | |
106
- | [no-unsafe-output-handling](./docs/rules/no-unsafe-output-handling.md) | CWE-94 | ASI05 | 9.8 | Prevent unexpected code execution from AI output | ๐Ÿ’ผ | | | | |
107
- | **ASI06: Memory Corruption** | - | ASI06 | - | _N/A (TypeScript/JS is memory-safe)_ | - | - | | - | |
108
- | [require-rag-content-validation](./docs/rules/require-rag-content-validation.md) | CWE-74 | ASI07 | 6.0 | Validate RAG content before use in prompts | | โš ๏ธ | | | |
109
- | [require-error-handling](./docs/rules/require-error-handling.md) | CWE-755 | ASI08 | 5.0 | Require error handling to prevent cascading failures | | | | ๐Ÿ’ก | |
110
- | [require-tool-confirmation](./docs/rules/require-tool-confirmation.md) | CWE-862 | ASI09 | 7.0 | Require human-in-the-loop for sensitive actions | ๐Ÿ’ผ | | | | |
111
- | [require-audit-logging](./docs/rules/require-audit-logging.md) | CWE-778 | ASI10 | 4.0 | Suggest audit logging for AI operations | | | | ๐Ÿ’ก | |
112
- ---
113
-
114
38
  ## ๐Ÿ”ง Supported AI SDK Functions
115
39
 
116
40
  | Function | Full Coverage |
@@ -124,6 +48,16 @@ export default [vercelAISecurity.configs.recommended];
124
48
 
125
49
  ---
126
50
 
51
+ ## โš™๏ธ Configuration Presets
52
+
53
+ | Preset | Description |
54
+ | :------------ | :--------------------------------------- |
55
+ | `recommended` | Balanced security (7 errors, 7 warnings) |
56
+ | `strict` | Maximum security (17 errors, 2 warnings) |
57
+ | `minimal` | Minimal config |
58
+
59
+ ---
60
+
127
61
  ## ๐Ÿ“Š Test Coverage
128
62
 
129
63
  | Metric | Coverage |
@@ -144,36 +78,51 @@ All rule messages follow a structured format optimized for AI coding assistants:
144
78
  Fix: Validate input before use | https://owasp.org/...
145
79
  ```
146
80
 
147
- ---
148
-
149
- ## ๐Ÿ“ฆ Compatibility
150
-
151
- | Package | Version |
152
- | -------------------- | ------------------------------ |
153
- | `ai` (Vercel AI SDK) | ^3.0.0 \|\| ^4.0.0 \|\| ^5.0.0 |
154
- | ESLint | ^8.0.0 \|\| ^9.0.0 |
155
- | Node.js | ^18.0.0 |
81
+ By providing this structured context (CWE, OWASP, Fix), we enable AI tools to **reason** about the security flaw rather than hallucinating. This allows Copilot/Cursor to suggest the _exact_ correct fix immediately.
82
+
83
+ ## Rules
84
+
85
+ **Legend**
86
+
87
+ | Icon | Description |
88
+ | :--: | :----------------------------------------------------------------- |
89
+ | ๐Ÿ’ผ | **Recommended**: Included in the recommended preset. |
90
+ | โš ๏ธ | **Warns**: Set towarn in recommended preset. |
91
+ | ๐Ÿ”ง | **Auto-fixable**: Automatically fixable by the `--fix` CLI option. |
92
+ | ๐Ÿ’ก | **Suggestions**: Providing code suggestions in IDE. |
93
+ | ๐Ÿšซ | **Deprecated**: This rule is deprecated. |
94
+
95
+ | Rule | CWE | OWASP | CVSS | Description | ๐Ÿ’ผ | โš ๏ธ | ๐Ÿ”ง | ๐Ÿ’ก | ๐Ÿšซ |
96
+ | :---------------------------------------------------------------------------------------------------------------------------- | :-----: | :---: | :--: | :------------------------------------------------------------------------------- | :-: | :-: | :-: | :-: | :-: |
97
+ | [require-validated-prompt](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-validated-prompt) | CWE-74 | | 9.0 | [require-validated-prompt](./docs/rules/require-validated-prompt.md) | ๐Ÿ’ผ | | | | |
98
+ | [no-sensitive-in-prompt](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-sensitive-in-prompt) | CWE-200 | | 8.0 | [no-sensitive-in-prompt](./docs/rules/no-sensitive-in-prompt.md) | ๐Ÿ’ผ | | | | |
99
+ | [no-training-data-exposure](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-training-data-exposure) | CWE-359 | | 7.0 | [no-training-data-exposure](./docs/rules/no-training-data-exposure.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
100
+ | [require-request-timeout](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-request-timeout) | CWE-400 | | 5.0 | [require-request-timeout](./docs/rules/require-request-timeout.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
101
+ | [no-unsafe-output-handling](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-unsafe-output-handling) | CWE-94 | | 9.8 | [no-unsafe-output-handling](./docs/rules/no-unsafe-output-handling.md) | ๐Ÿ’ผ | | | | |
102
+ | [require-tool-confirmation](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-tool-confirmation) | CWE-862 | | 7.0 | [require-tool-confirmation](./docs/rules/require-tool-confirmation.md) | ๐Ÿ’ผ | | | | |
103
+ | [no-system-prompt-leak](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-system-prompt-leak) | CWE-200 | | 7.5 | [no-system-prompt-leak](./docs/rules/no-system-prompt-leak.md) | ๐Ÿ’ผ | | | | |
104
+ | [require-embedding-validation](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-embedding-validation) | CWE-20 | | 5.5 | [require-embedding-validation](./docs/rules/require-embedding-validation.md) | | | | ๐Ÿ’ก | |
105
+ | [require-output-validation](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-output-validation) | CWE-707 | | 5.0 | [require-output-validation](./docs/rules/require-output-validation.md) | | | | ๐Ÿ’ก | |
106
+ | [require-max-tokens](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-max-tokens) | CWE-770 | | 6.5 | [require-max-tokens](./docs/rules/require-max-tokens.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
107
+ | [require-max-steps](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-max-steps) | CWE-834 | | 6.5 | [require-max-steps](./docs/rules/require-max-steps.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
108
+ | [require-abort-signal](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-abort-signal) | CWE-404 | | 4.0 | [require-abort-signal](./docs/rules/require-abort-signal.md) | | | | ๐Ÿ’ก | |
109
+ | [no-dynamic-system-prompt](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-dynamic-system-prompt) | CWE-74 | | 8.0 | [no-dynamic-system-prompt](./docs/rules/no-dynamic-system-prompt.md) | ๐Ÿ’ผ | | | | |
110
+ | [require-tool-schema](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-tool-schema) | CWE-20 | | 7.5 | [require-tool-schema](./docs/rules/require-tool-schema.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
111
+ | [no-hardcoded-api-keys](https://eslint.interlace.tools/docs/vercel-ai-security/rules/no-hardcoded-api-keys) | CWE-798 | | 8.5 | [no-hardcoded-api-keys](./docs/rules/no-hardcoded-api-keys.md) | ๐Ÿ’ผ | | | | |
112
+ | [require-output-filtering](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-output-filtering) | CWE-200 | | 6.5 | [require-output-filtering](./docs/rules/require-output-filtering.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
113
+ | [require-rag-content-validation](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-rag-content-validation) | CWE-74 | | 6.0 | [require-rag-content-validation](./docs/rules/require-rag-content-validation.md) | ๐Ÿ’ผ | โš ๏ธ | | | |
114
+ | [require-error-handling](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-error-handling) | CWE-755 | | 5.0 | [require-error-handling](./docs/rules/require-error-handling.md) | | | | ๐Ÿ’ก | |
115
+ | [require-audit-logging](https://eslint.interlace.tools/docs/vercel-ai-security/rules/require-audit-logging) | CWE-778 | | 4.0 | [require-audit-logging](./docs/rules/require-audit-logging.md) | | | | ๐Ÿ’ก | |
156
116
 
157
117
  ---
158
118
 
159
- ## ๐Ÿ”— Related ESLint Plugins
160
-
161
- Part of the **Interlace ESLint Ecosystem** โ€” AI-native security plugins with LLM-optimized error messages:
162
-
163
- | Plugin | Downloads | Description | Rule | CWE | OWASP | CVSS | Description | ๐Ÿ’ผ | โš ๏ธ | ๐Ÿ”ง | ๐Ÿ’ก | ๐Ÿšซ |
164
- | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: |
165
- | [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugin-secure-coding) | | | | | | | | | |
166
- | [`eslint-plugin-jwt`](https://www.npmjs.com/package/eslint-plugin-jwt) | | | | | | | | | |
167
- | [`eslint-plugin-crypto`](https://www.npmjs.com/package/eslint-plugin-crypto) | | | | | | | | | |
168
- | [`eslint-plugin-pg`](https://www.npmjs.com/package/eslint-plugin-pg) | | | | | | | | | |
169
- | [`eslint-plugin-express-security`](https://www.npmjs.com/package/eslint-plugin-express-security) | | | | | | | | | |
170
- | [`eslint-plugin-nestjs-security`](https://www.npmjs.com/package/eslint-plugin-nestjs-security) | | | | | | | | | |
171
- | [`eslint-plugin-lambda-security`](https://www.npmjs.com/package/eslint-plugin-lambda-security) | | | | | | | | | |
172
- | [`eslint-plugin-browser-security`](https://www.npmjs.com/package/eslint-plugin-browser-security) | | | | | | | | | |
173
- | [`eslint-plugin-import-next`](https://www.npmjs.com/package/eslint-plugin-import-next) | | | | | | | | | |
174
- ## ๐Ÿ“„ License
119
+ ## ๐Ÿ“ฆ Compatibility
175
120
 
176
- MIT ยฉ [Ofri Peretz](https://github.com/ofri-peretz)
121
+ | Package | Version |
122
+ | -------------------- | --------------------------------------------------------------------------------------------------------- |
123
+ | `ai` (Vercel AI SDK) | [![npm](https://img.shields.io/npm/v/ai.svg?style=flat-square)](https://www.npmjs.com/package/ai) |
124
+ | ESLint | [![npm](https://img.shields.io/npm/v/eslint.svg?style=flat-square)](https://www.npmjs.com/package/eslint) |
125
+ | Node.js | [![node](https://img.shields.io/badge/node-%5E18.0.0-green?style=flat-square)](https://nodejs.org/) |
177
126
 
178
127
  ---
179
128
 
@@ -197,3 +146,38 @@ await generateText({ prompt: internalPrompt });
197
146
  ### Why is ASI06 (Memory Corruption) not covered?
198
147
 
199
148
  TypeScript/JavaScript are memory-safe languages. Memory corruption vulnerabilities (buffer overflows, use-after-free, etc.) are not possible in these environments.
149
+
150
+ ## ๐Ÿ“š Supported Libraries
151
+
152
+ | Library | npm | Downloads | Detection |
153
+ | -------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------ |
154
+ | `ai` (Vercel AI SDK) | [![npm](https://img.shields.io/npm/v/ai.svg?style=flat-square)](https://www.npmjs.com/package/ai) | [![downloads](https://img.shields.io/npm/dt/ai.svg?style=flat-square)](https://www.npmjs.com/package/ai) | Prompt Injection, Data Leakage |
155
+
156
+ ## ๐Ÿ”— Related ESLint Plugins
157
+
158
+ Part of the **Interlace ESLint Ecosystem** โ€” AI-native security plugins with LLM-optimized error messages:
159
+
160
+ | Plugin | Downloads | Description |
161
+ | :--------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------ |
162
+ | [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugin-secure-coding) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-secure-coding.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-secure-coding) | General security rules & OWASP guidelines. |
163
+ | [`eslint-plugin-pg`](https://www.npmjs.com/package/eslint-plugin-pg) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-pg.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-pg) | PostgreSQL security & best practices. |
164
+ | [`eslint-plugin-crypto`](https://www.npmjs.com/package/eslint-plugin-crypto) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-crypto.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-crypto) | NodeJS Cryptography security rules. |
165
+ | [`eslint-plugin-jwt`](https://www.npmjs.com/package/eslint-plugin-jwt) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-jwt.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-jwt) | JWT security & best practices. |
166
+ | [`eslint-plugin-browser-security`](https://www.npmjs.com/package/eslint-plugin-browser-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-browser-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-browser-security) | Browser-specific security & XSS prevention. |
167
+ | [`eslint-plugin-vercel-ai-security`](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-vercel-ai-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security) | Vercel AI SDK security rules. |
168
+ | [`eslint-plugin-express-security`](https://www.npmjs.com/package/eslint-plugin-express-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-express-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-express-security) | Express.js security hardening rules. |
169
+ | [`eslint-plugin-lambda-security`](https://www.npmjs.com/package/eslint-plugin-lambda-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-lambda-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-lambda-security) | AWS Lambda security best practices. |
170
+ | [`eslint-plugin-nestjs-security`](https://www.npmjs.com/package/eslint-plugin-nestjs-security) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-nestjs-security.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-nestjs-security) | NestJS security rules & patterns. |
171
+ | [`eslint-plugin-import-next`](https://www.npmjs.com/package/eslint-plugin-import-next) | [![downloads](https://img.shields.io/npm/dt/eslint-plugin-import-next.svg?style=flat-square)](https://www.npmjs.com/package/eslint-plugin-import-next) | Next-gen import sorting & architecture. |
172
+
173
+ ## ๐Ÿ“„ License
174
+
175
+ MIT ยฉ [Ofri Peretz](https://github.com/ofri-peretz)
176
+
177
+ <p align="center">
178
+ <a href="https://eslint.interlace.tools/docs/vercel-ai-security"><img src="https://eslint.interlace.tools/images/og-ai-security.png" alt="ESLint Interlace Plugin" width="300" /></a>
179
+ </p>
180
+
181
+ <p align="center">
182
+ <a href="https://eslint.interlace.tools/docs/vercel-ai-security"><img src="https://eslint.interlace.tools/images/og-vercel-ai-security.png" alt="ESLint Interlace Plugin" width="300" /></a>
183
+ </p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-vercel-ai-security",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Security-focused ESLint plugin for Vercel AI SDK. SDK-aware rules for generateText, streamText, tools, and streaming patterns with full type knowledge.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -41,6 +41,7 @@
41
41
  "eslint",
42
42
  "eslint-plugin",
43
43
  "eslintplugin",
44
+ "interlace-security",
44
45
  "security",
45
46
  "vercel",
46
47
  "vercel-ai",
@@ -63,12 +64,15 @@
63
64
  "engines": {
64
65
  "node": ">=18.0.0"
65
66
  },
66
- "peerDependencies": {
67
- "eslint": "^8.0.0 || ^9.0.0"
67
+ "peerDependencies": {},
68
+ "peerDependenciesMeta": {
69
+ "ai": {
70
+ "optional": true
71
+ }
68
72
  },
69
73
  "dependencies": {
70
- "@interlace/eslint-devkit": "^1.0.0",
71
- "tslib": "^2.3.0"
74
+ "tslib": "^2.3.0",
75
+ "@interlace/eslint-devkit": "^1.2.1"
72
76
  },
73
77
  "devDependencies": {
74
78
  "@ai-sdk/openai": "^2.0.86",
@@ -8,5 +8,7 @@ export interface Options {
8
8
  allowStaticTemplates?: boolean;
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const noDynamicSystemPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<"dynamicSystemPrompt", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const noDynamicSystemPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<"dynamicSystemPrompt", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  apiKeyPatterns?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const noHardcodedApiKeys: import("@typescript-eslint/utils/ts-eslint").RuleModule<"hardcodedApiKey", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const noHardcodedApiKeys: import("@typescript-eslint/utils/ts-eslint").RuleModule<"hardcodedApiKey", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  sensitivePatterns?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const noSensitiveInPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<"sensitiveInPrompt", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const noSensitiveInPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<"sensitiveInPrompt", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  systemPromptPatterns?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const noSystemPromptLeak: import("@typescript-eslint/utils/ts-eslint").RuleModule<"systemPromptLeak", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const noSystemPromptLeak: import("@typescript-eslint/utils/ts-eslint").RuleModule<"systemPromptLeak", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  trainingPatterns?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const noTrainingDataExposure: import("@typescript-eslint/utils/ts-eslint").RuleModule<"trainingDataExposure", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const noTrainingDataExposure: import("@typescript-eslint/utils/ts-eslint").RuleModule<"trainingDataExposure", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -60,7 +60,6 @@ exports.noTrainingDataExposure = (0, eslint_devkit_1.createRule)({
60
60
  const trainingPatterns = options.trainingPatterns ?? [
61
61
  'train', 'training', 'finetune', 'feedback',
62
62
  ];
63
- const sourceCode = context.sourceCode || context.getSourceCode();
64
63
  /**
65
64
  * Check if identifier suggests training
66
65
  */
@@ -9,5 +9,7 @@ export interface Options {
9
9
  aiOutputPatterns?: string[];
10
10
  }
11
11
  type RuleOptions = [Options?];
12
- export declare const noUnsafeOutputHandling: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
12
+ export declare const noUnsafeOutputHandling: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
13
+ name: string;
14
+ };
13
15
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  targetFunctions?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireAbortSignal: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingAbortSignal", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireAbortSignal: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingAbortSignal", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  allowInTests?: boolean;
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireAuditLogging: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingAuditLogging", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireAuditLogging: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingAuditLogging", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -10,5 +10,7 @@ export interface Options {
10
10
  validatorFunctions?: string[];
11
11
  }
12
12
  type RuleOptions = [Options?];
13
- export declare const requireEmbeddingValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unvalidatedEmbedding", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ export declare const requireEmbeddingValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unvalidatedEmbedding", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
14
+ name: string;
15
+ };
14
16
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  allowInTests?: boolean;
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireErrorHandling: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingErrorHandling", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireErrorHandling: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingErrorHandling", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  suggestedMaxSteps?: number;
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireMaxSteps: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingMaxSteps", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireMaxSteps: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingMaxSteps", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -10,5 +10,7 @@ export interface Options {
10
10
  targetFunctions?: string[];
11
11
  }
12
12
  type RuleOptions = [Options?];
13
- export declare const requireMaxTokens: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingMaxTokens", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ export declare const requireMaxTokens: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingMaxTokens", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
14
+ name: string;
15
+ };
14
16
  export {};
@@ -10,5 +10,7 @@ export interface Options {
10
10
  filterFunctions?: string[];
11
11
  }
12
12
  type RuleOptions = [Options?];
13
- export declare const requireOutputFiltering: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingOutputFilter", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ export declare const requireOutputFiltering: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingOutputFilter", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
14
+ name: string;
15
+ };
14
16
  export {};
@@ -10,5 +10,7 @@ export interface Options {
10
10
  validatorFunctions?: string[];
11
11
  }
12
12
  type RuleOptions = [Options?];
13
- export declare const requireOutputValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unvalidatedOutput", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ export declare const requireOutputValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unvalidatedOutput", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
14
+ name: string;
15
+ };
14
16
  export {};
@@ -10,5 +10,7 @@ export interface Options {
10
10
  validatorFunctions?: string[];
11
11
  }
12
12
  type RuleOptions = [Options?];
13
- export declare const requireRagContentValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsanitizedRagContent", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
13
+ export declare const requireRagContentValidation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsanitizedRagContent", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
14
+ name: string;
15
+ };
14
16
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  allowInTests?: boolean;
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireRequestTimeout: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingTimeout", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireRequestTimeout: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingTimeout", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -8,5 +8,7 @@ export interface Options {
8
8
  destructivePatterns?: string[];
9
9
  }
10
10
  type RuleOptions = [Options?];
11
- export declare const requireToolConfirmation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingConfirmation", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ export declare const requireToolConfirmation: import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingConfirmation", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
12
+ name: string;
13
+ };
12
14
  export {};
@@ -9,5 +9,7 @@ export interface Options {
9
9
  allowInTests?: boolean;
10
10
  }
11
11
  type RuleOptions = [Options?];
12
- export declare const requireToolSchema: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
12
+ export declare const requireToolSchema: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
13
+ name: string;
14
+ };
13
15
  export {};
@@ -13,5 +13,7 @@ export interface Options {
13
13
  allowInTests?: boolean;
14
14
  }
15
15
  type RuleOptions = [Options?];
16
- export declare const requireValidatedPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
16
+ export declare const requireValidatedPrompt: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
17
+ name: string;
18
+ };
17
19
  export {};