eslint-plugin-node-security 4.0.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/CHANGELOG.md +83 -0
- package/README.md +50 -0
- package/package.json +79 -0
- package/src/index.d.ts +10 -0
- package/src/index.js +118 -0
- package/src/index.js.map +1 -0
- package/src/rules/detect-child-process/index.d.ts +30 -0
- package/src/rules/detect-child-process/index.js +535 -0
- package/src/rules/detect-child-process/index.js.map +1 -0
- package/src/rules/detect-eval-with-expression/index.d.ts +28 -0
- package/src/rules/detect-eval-with-expression/index.js +398 -0
- package/src/rules/detect-eval-with-expression/index.js.map +1 -0
- package/src/rules/detect-non-literal-fs-filename/index.d.ts +26 -0
- package/src/rules/detect-non-literal-fs-filename/index.js +460 -0
- package/src/rules/detect-non-literal-fs-filename/index.js.map +1 -0
- package/src/rules/detect-suspicious-dependencies/index.d.ts +12 -0
- package/src/rules/detect-suspicious-dependencies/index.js +77 -0
- package/src/rules/detect-suspicious-dependencies/index.js.map +1 -0
- package/src/rules/lock-file/index.d.ts +13 -0
- package/src/rules/lock-file/index.js +94 -0
- package/src/rules/lock-file/index.js.map +1 -0
- package/src/rules/no-arbitrary-file-access/index.d.ts +12 -0
- package/src/rules/no-arbitrary-file-access/index.js +201 -0
- package/src/rules/no-arbitrary-file-access/index.js.map +1 -0
- package/src/rules/no-buffer-overread/index.d.ts +39 -0
- package/src/rules/no-buffer-overread/index.js +612 -0
- package/src/rules/no-buffer-overread/index.js.map +1 -0
- package/src/rules/no-cryptojs/index.d.ts +24 -0
- package/src/rules/no-cryptojs/index.js +104 -0
- package/src/rules/no-cryptojs/index.js.map +1 -0
- package/src/rules/no-cryptojs-weak-random/index.d.ts +24 -0
- package/src/rules/no-cryptojs-weak-random/index.js +112 -0
- package/src/rules/no-cryptojs-weak-random/index.js.map +1 -0
- package/src/rules/no-data-in-temp-storage/index.d.ts +14 -0
- package/src/rules/no-data-in-temp-storage/index.js +99 -0
- package/src/rules/no-data-in-temp-storage/index.js.map +1 -0
- package/src/rules/no-deprecated-cipher-method/index.d.ts +23 -0
- package/src/rules/no-deprecated-cipher-method/index.js +118 -0
- package/src/rules/no-deprecated-cipher-method/index.js.map +1 -0
- package/src/rules/no-dynamic-dependency-loading/index.d.ts +12 -0
- package/src/rules/no-dynamic-dependency-loading/index.js +55 -0
- package/src/rules/no-dynamic-dependency-loading/index.js.map +1 -0
- package/src/rules/no-dynamic-require/index.d.ts +21 -0
- package/src/rules/no-dynamic-require/index.js +122 -0
- package/src/rules/no-dynamic-require/index.js.map +1 -0
- package/src/rules/no-ecb-mode/index.d.ts +23 -0
- package/src/rules/no-ecb-mode/index.js +113 -0
- package/src/rules/no-ecb-mode/index.js.map +1 -0
- package/src/rules/no-insecure-key-derivation/index.d.ts +24 -0
- package/src/rules/no-insecure-key-derivation/index.js +116 -0
- package/src/rules/no-insecure-key-derivation/index.js.map +1 -0
- package/src/rules/no-insecure-rsa-padding/index.d.ts +24 -0
- package/src/rules/no-insecure-rsa-padding/index.js +110 -0
- package/src/rules/no-insecure-rsa-padding/index.js.map +1 -0
- package/src/rules/no-pii-in-logs/index.d.ts +12 -0
- package/src/rules/no-pii-in-logs/index.js +74 -0
- package/src/rules/no-pii-in-logs/index.js.map +1 -0
- package/src/rules/no-self-signed-certs/index.d.ts +23 -0
- package/src/rules/no-self-signed-certs/index.js +116 -0
- package/src/rules/no-self-signed-certs/index.js.map +1 -0
- package/src/rules/no-sha1-hash/index.d.ts +24 -0
- package/src/rules/no-sha1-hash/index.js +128 -0
- package/src/rules/no-sha1-hash/index.js.map +1 -0
- package/src/rules/no-static-iv/index.d.ts +23 -0
- package/src/rules/no-static-iv/index.js +147 -0
- package/src/rules/no-static-iv/index.js.map +1 -0
- package/src/rules/no-timing-unsafe-compare/index.d.ts +23 -0
- package/src/rules/no-timing-unsafe-compare/index.js +114 -0
- package/src/rules/no-timing-unsafe-compare/index.js.map +1 -0
- package/src/rules/no-toctou-vulnerability/index.d.ts +26 -0
- package/src/rules/no-toctou-vulnerability/index.js +214 -0
- package/src/rules/no-toctou-vulnerability/index.js.map +1 -0
- package/src/rules/no-unsafe-dynamic-require/index.d.ts +19 -0
- package/src/rules/no-unsafe-dynamic-require/index.js +112 -0
- package/src/rules/no-unsafe-dynamic-require/index.js.map +1 -0
- package/src/rules/no-weak-cipher-algorithm/index.d.ts +25 -0
- package/src/rules/no-weak-cipher-algorithm/index.js +190 -0
- package/src/rules/no-weak-cipher-algorithm/index.js.map +1 -0
- package/src/rules/no-weak-hash-algorithm/index.d.ts +25 -0
- package/src/rules/no-weak-hash-algorithm/index.js +218 -0
- package/src/rules/no-weak-hash-algorithm/index.js.map +1 -0
- package/src/rules/no-zip-slip/index.d.ts +35 -0
- package/src/rules/no-zip-slip/index.js +451 -0
- package/src/rules/no-zip-slip/index.js.map +1 -0
- package/src/rules/prefer-native-crypto/index.d.ts +23 -0
- package/src/rules/prefer-native-crypto/index.js +124 -0
- package/src/rules/prefer-native-crypto/index.js.map +1 -0
- package/src/rules/require-dependency-integrity/index.d.ts +12 -0
- package/src/rules/require-dependency-integrity/index.js +70 -0
- package/src/rules/require-dependency-integrity/index.js.map +1 -0
- package/src/rules/require-secure-credential-storage/index.d.ts +12 -0
- package/src/rules/require-secure-credential-storage/index.js +54 -0
- package/src/rules/require-secure-credential-storage/index.js.map +1 -0
- package/src/rules/require-secure-deletion/index.d.ts +12 -0
- package/src/rules/require-secure-deletion/index.js +46 -0
- package/src/rules/require-secure-deletion/index.js.map +1 -0
- package/src/rules/require-storage-encryption/index.d.ts +12 -0
- package/src/rules/require-storage-encryption/index.js +54 -0
- package/src/rules/require-storage-encryption/index.js.map +1 -0
- package/src/types/index.d.ts +24 -0
- package/src/types/index.js +8 -0
- package/src/types/index.js.map +1 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
4
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
5
|
+
* MIT license that can be found in the LICENSE file.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.noBufferOverread = void 0;
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.noBufferOverread = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'no-buffer-overread',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'problem',
|
|
14
|
+
docs: {
|
|
15
|
+
description: 'Detects buffer access beyond bounds',
|
|
16
|
+
},
|
|
17
|
+
fixable: 'code',
|
|
18
|
+
hasSuggestions: true,
|
|
19
|
+
messages: {
|
|
20
|
+
bufferOverread: (0, eslint_devkit_1.formatLLMMessage)({
|
|
21
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
22
|
+
issueName: 'Buffer Overread',
|
|
23
|
+
cwe: 'CWE-126',
|
|
24
|
+
description: 'Buffer access beyond allocated bounds',
|
|
25
|
+
severity: '{{severity}}',
|
|
26
|
+
fix: '{{safeAlternative}}',
|
|
27
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/126.html',
|
|
28
|
+
}),
|
|
29
|
+
unsafeBufferAccess: (0, eslint_devkit_1.formatLLMMessage)({
|
|
30
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
31
|
+
issueName: 'Unsafe Buffer Access',
|
|
32
|
+
cwe: 'CWE-126',
|
|
33
|
+
description: 'Buffer accessed without bounds validation',
|
|
34
|
+
severity: 'HIGH',
|
|
35
|
+
fix: 'Add bounds check before buffer access',
|
|
36
|
+
documentationLink: 'https://nodejs.org/api/buffer.html',
|
|
37
|
+
}),
|
|
38
|
+
missingBoundsCheck: (0, eslint_devkit_1.formatLLMMessage)({
|
|
39
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
40
|
+
issueName: 'Missing Bounds Check',
|
|
41
|
+
cwe: 'CWE-126',
|
|
42
|
+
description: 'Buffer operation missing bounds validation',
|
|
43
|
+
severity: 'MEDIUM',
|
|
44
|
+
fix: 'Validate indices before buffer operations',
|
|
45
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/126.html',
|
|
46
|
+
}),
|
|
47
|
+
negativeBufferIndex: (0, eslint_devkit_1.formatLLMMessage)({
|
|
48
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
49
|
+
issueName: 'Negative Buffer Index',
|
|
50
|
+
cwe: 'CWE-126',
|
|
51
|
+
description: 'Negative index used for buffer access',
|
|
52
|
+
severity: 'MEDIUM',
|
|
53
|
+
fix: 'Ensure buffer indices are non-negative',
|
|
54
|
+
documentationLink: 'https://nodejs.org/api/buffer.html',
|
|
55
|
+
}),
|
|
56
|
+
userControlledBufferIndex: (0, eslint_devkit_1.formatLLMMessage)({
|
|
57
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
58
|
+
issueName: 'User Controlled Buffer Index',
|
|
59
|
+
cwe: 'CWE-126',
|
|
60
|
+
description: 'Buffer accessed with user-controlled index',
|
|
61
|
+
severity: 'HIGH',
|
|
62
|
+
fix: 'Validate user input before using as buffer index',
|
|
63
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/126.html',
|
|
64
|
+
}),
|
|
65
|
+
unsafeBufferSlice: (0, eslint_devkit_1.formatLLMMessage)({
|
|
66
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
67
|
+
issueName: 'Unsafe Buffer Slice',
|
|
68
|
+
cwe: 'CWE-126',
|
|
69
|
+
description: 'Buffer slice with unvalidated indices',
|
|
70
|
+
severity: 'MEDIUM',
|
|
71
|
+
fix: 'Validate slice start/end indices',
|
|
72
|
+
documentationLink: 'https://nodejs.org/api/buffer.html#bufslicestart-end',
|
|
73
|
+
}),
|
|
74
|
+
bufferLengthNotChecked: (0, eslint_devkit_1.formatLLMMessage)({
|
|
75
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
76
|
+
issueName: 'Buffer Length Not Checked',
|
|
77
|
+
cwe: 'CWE-126',
|
|
78
|
+
description: 'Buffer length not validated before access',
|
|
79
|
+
severity: 'MEDIUM',
|
|
80
|
+
fix: 'Check buffer.length before operations',
|
|
81
|
+
documentationLink: 'https://nodejs.org/api/buffer.html#buflength',
|
|
82
|
+
}),
|
|
83
|
+
useSafeBufferAccess: (0, eslint_devkit_1.formatLLMMessage)({
|
|
84
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
85
|
+
issueName: 'Use Safe Buffer Access',
|
|
86
|
+
description: 'Use bounds-checked buffer access methods',
|
|
87
|
+
severity: 'LOW',
|
|
88
|
+
fix: 'Use buffer.read*() with offset validation or safe wrapper functions',
|
|
89
|
+
documentationLink: 'https://nodejs.org/api/buffer.html',
|
|
90
|
+
}),
|
|
91
|
+
validateBufferIndices: (0, eslint_devkit_1.formatLLMMessage)({
|
|
92
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
93
|
+
issueName: 'Validate Buffer Indices',
|
|
94
|
+
description: 'Validate buffer indices before use',
|
|
95
|
+
severity: 'LOW',
|
|
96
|
+
fix: 'Check 0 <= index < buffer.length',
|
|
97
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/126.html',
|
|
98
|
+
}),
|
|
99
|
+
checkBufferBounds: (0, eslint_devkit_1.formatLLMMessage)({
|
|
100
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
101
|
+
issueName: 'Check Buffer Bounds',
|
|
102
|
+
description: 'Always check buffer bounds',
|
|
103
|
+
severity: 'LOW',
|
|
104
|
+
fix: 'Validate buffer operations against buffer.length',
|
|
105
|
+
documentationLink: 'https://nodejs.org/api/buffer.html#buflength',
|
|
106
|
+
}),
|
|
107
|
+
strategyBoundsChecking: (0, eslint_devkit_1.formatLLMMessage)({
|
|
108
|
+
icon: eslint_devkit_1.MessageIcons.STRATEGY,
|
|
109
|
+
issueName: 'Bounds Checking Strategy',
|
|
110
|
+
description: 'Implement comprehensive bounds checking',
|
|
111
|
+
severity: 'LOW',
|
|
112
|
+
fix: 'Validate all buffer indices and lengths before operations',
|
|
113
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/126.html',
|
|
114
|
+
}),
|
|
115
|
+
strategyInputValidation: (0, eslint_devkit_1.formatLLMMessage)({
|
|
116
|
+
icon: eslint_devkit_1.MessageIcons.STRATEGY,
|
|
117
|
+
issueName: 'Input Validation Strategy',
|
|
118
|
+
description: 'Validate user input used as buffer indices',
|
|
119
|
+
severity: 'LOW',
|
|
120
|
+
fix: 'Sanitize and validate all user input before buffer operations',
|
|
121
|
+
documentationLink: 'https://nodejs.org/api/buffer.html',
|
|
122
|
+
}),
|
|
123
|
+
strategySafeBuffers: (0, eslint_devkit_1.formatLLMMessage)({
|
|
124
|
+
icon: eslint_devkit_1.MessageIcons.STRATEGY,
|
|
125
|
+
issueName: 'Safe Buffer Strategy',
|
|
126
|
+
description: 'Use safe buffer wrapper libraries',
|
|
127
|
+
severity: 'LOW',
|
|
128
|
+
fix: 'Use libraries that provide bounds-checked buffer operations',
|
|
129
|
+
documentationLink: 'https://www.npmjs.com/package/safe-buffer',
|
|
130
|
+
})
|
|
131
|
+
},
|
|
132
|
+
schema: [
|
|
133
|
+
{
|
|
134
|
+
type: 'object',
|
|
135
|
+
properties: {
|
|
136
|
+
bufferMethods: {
|
|
137
|
+
type: 'array',
|
|
138
|
+
items: { type: 'string' },
|
|
139
|
+
default: ['readUInt8', 'readUInt16LE', 'readUInt32LE', 'readInt8', 'readInt16LE', 'readInt32LE', 'writeUInt8', 'writeUInt16LE', 'writeUInt32LE', 'slice', 'copy'],
|
|
140
|
+
},
|
|
141
|
+
boundsCheckFunctions: {
|
|
142
|
+
type: 'array',
|
|
143
|
+
items: { type: 'string' },
|
|
144
|
+
default: ['validateIndex', 'checkBounds', 'safeIndex', 'validateBufferIndex'],
|
|
145
|
+
},
|
|
146
|
+
bufferTypes: {
|
|
147
|
+
type: 'array',
|
|
148
|
+
items: { type: 'string' },
|
|
149
|
+
default: ['Buffer', 'Uint8Array', 'ArrayBuffer', 'DataView'],
|
|
150
|
+
},
|
|
151
|
+
trustedSanitizers: {
|
|
152
|
+
type: 'array',
|
|
153
|
+
items: { type: 'string' },
|
|
154
|
+
default: [],
|
|
155
|
+
description: 'Additional function names to consider as buffer index validators',
|
|
156
|
+
},
|
|
157
|
+
trustedAnnotations: {
|
|
158
|
+
type: 'array',
|
|
159
|
+
items: { type: 'string' },
|
|
160
|
+
default: [],
|
|
161
|
+
description: 'Additional JSDoc annotations to consider as safe markers',
|
|
162
|
+
},
|
|
163
|
+
strictMode: {
|
|
164
|
+
type: 'boolean',
|
|
165
|
+
default: false,
|
|
166
|
+
description: 'Disable all false positive detection (strict mode)',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
additionalProperties: false,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
defaultOptions: [
|
|
174
|
+
{
|
|
175
|
+
bufferMethods: ['readUInt8', 'readUInt16LE', 'readUInt32LE', 'readInt8', 'readInt16LE', 'readInt32LE', 'writeUInt8', 'writeUInt16LE', 'writeUInt32LE', 'slice', 'copy'],
|
|
176
|
+
boundsCheckFunctions: ['validateIndex', 'checkBounds', 'safeIndex', 'validateBufferIndex'],
|
|
177
|
+
bufferTypes: ['Buffer', 'Uint8Array', 'ArrayBuffer', 'DataView'],
|
|
178
|
+
trustedSanitizers: [],
|
|
179
|
+
trustedAnnotations: [],
|
|
180
|
+
strictMode: false,
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
create(context) {
|
|
184
|
+
const options = context.options[0] || {};
|
|
185
|
+
const { bufferMethods = ['readUInt8', 'readUInt16LE', 'readUInt32LE', 'readInt8', 'readInt16LE', 'readInt32LE', 'writeUInt8', 'writeUInt16LE', 'writeUInt32LE', 'slice', 'copy'], boundsCheckFunctions = ['validateIndex', 'checkBounds', 'safeIndex', 'validateBufferIndex'], bufferTypes = ['Buffer', 'Uint8Array', 'ArrayBuffer', 'DataView'], trustedSanitizers = [], trustedAnnotations = [], strictMode = false, } = options;
|
|
186
|
+
const sourceCode = context.sourceCode || context.sourceCode;
|
|
187
|
+
const filename = context.filename || context.getFilename();
|
|
188
|
+
// Create safety checker for false positive detection
|
|
189
|
+
const safetyChecker = (0, eslint_devkit_1.createSafetyChecker)({
|
|
190
|
+
trustedSanitizers,
|
|
191
|
+
trustedAnnotations,
|
|
192
|
+
trustedOrmPatterns: [],
|
|
193
|
+
strictMode,
|
|
194
|
+
});
|
|
195
|
+
// Pre-compute Sets for O(1) lookups (performance optimization)
|
|
196
|
+
const bufferTypesSet = new Set(bufferTypes.map(t => t.toLowerCase()));
|
|
197
|
+
const userControlledKeywords = new Set(['req', 'request', 'query', 'params', 'input', 'user', 'offset', 'index', 'body']);
|
|
198
|
+
// Track buffer variables
|
|
199
|
+
const bufferVars = new Set();
|
|
200
|
+
/**
|
|
201
|
+
* Check if variable is a buffer type
|
|
202
|
+
* Uses Set-based lookup for O(1) performance
|
|
203
|
+
*/
|
|
204
|
+
const isBufferType = (varName) => {
|
|
205
|
+
if (bufferVars.has(varName))
|
|
206
|
+
return true;
|
|
207
|
+
const lowerName = varName.toLowerCase();
|
|
208
|
+
for (const type of bufferTypesSet) {
|
|
209
|
+
if (lowerName.includes(type))
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
return false;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Check if index is user-controlled
|
|
216
|
+
* Uses Set-based keyword matching for O(1) lookups
|
|
217
|
+
*/
|
|
218
|
+
const isUserControlledIndex = (indexNode) => {
|
|
219
|
+
if (indexNode.type === 'Identifier') {
|
|
220
|
+
const varName = indexNode.name.toLowerCase();
|
|
221
|
+
// Check each part of the variable name against keywords Set
|
|
222
|
+
for (const keyword of userControlledKeywords) {
|
|
223
|
+
if (varName.includes(keyword))
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
// Trace variable definition
|
|
227
|
+
let currentScope = sourceCode.getScope(indexNode);
|
|
228
|
+
let variable = null;
|
|
229
|
+
while (currentScope) {
|
|
230
|
+
variable = currentScope.variables.find(v => v.name === indexNode.name) || null;
|
|
231
|
+
if (variable)
|
|
232
|
+
break;
|
|
233
|
+
currentScope = currentScope.upper;
|
|
234
|
+
}
|
|
235
|
+
if (variable && variable.defs.length > 0) {
|
|
236
|
+
const def = variable.defs[0];
|
|
237
|
+
if (def.type === 'Variable' && def.node.init) {
|
|
238
|
+
const init = def.node.init;
|
|
239
|
+
// Check MemberExpression involving user keywords (e.g. req.body.index)
|
|
240
|
+
if (init.type === 'MemberExpression') {
|
|
241
|
+
const objectText = sourceCode.getText(init.object).toLowerCase();
|
|
242
|
+
const propertyText = sourceCode.getText(init.property).toLowerCase();
|
|
243
|
+
const keywords = ['req', 'request', 'query', 'params', 'input', 'user', 'body'];
|
|
244
|
+
if (keywords.some(k => objectText.includes(k) || propertyText.includes(k))) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Check CallExpression with user-controlled arguments (Number(req.query.index), parseInt(), etc.)
|
|
249
|
+
if (init.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression) {
|
|
250
|
+
// Check if callee is a type conversion function
|
|
251
|
+
const typeConversionFunctions = ['number', 'parseint', 'parsefloat', 'string', 'boolean'];
|
|
252
|
+
let isTypeConversion = false;
|
|
253
|
+
if (init.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
254
|
+
isTypeConversion = typeConversionFunctions.includes(init.callee.name.toLowerCase());
|
|
255
|
+
}
|
|
256
|
+
// If it's a type conversion, check if the argument is user-controlled
|
|
257
|
+
if (isTypeConversion && init.arguments.length > 0) {
|
|
258
|
+
return isUserControlledIndex(init.arguments[0]);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Recursive check for Identifier assignment
|
|
262
|
+
if (init.type === 'Identifier' && init.name !== indexNode.name) {
|
|
263
|
+
return isUserControlledIndex(init);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Check CallExpression arguments (Number(req.query.index))
|
|
269
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression) {
|
|
270
|
+
const typeConversionFunctions = ['Number', 'parseInt', 'parseFloat', 'String', 'Boolean'];
|
|
271
|
+
if (indexNode.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
272
|
+
typeConversionFunctions.includes(indexNode.callee.name)) {
|
|
273
|
+
// Check if arguments are user-controlled
|
|
274
|
+
for (const arg of indexNode.arguments) {
|
|
275
|
+
if (isUserControlledIndex(arg)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Check MemberExpression (req.query.index)
|
|
282
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression) {
|
|
283
|
+
const text = sourceCode.getText(indexNode).toLowerCase();
|
|
284
|
+
const keywords = ['req.', 'request.', 'query.', 'params.', 'body.', 'input.', 'user.'];
|
|
285
|
+
if (keywords.some(k => text.includes(k))) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Check if index has been validated
|
|
293
|
+
*/
|
|
294
|
+
const isIndexValidated = (indexNode) => {
|
|
295
|
+
// If it's a literal number, check if it's non-negative
|
|
296
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.Literal && typeof indexNode.value === 'number') {
|
|
297
|
+
return indexNode.value >= 0;
|
|
298
|
+
}
|
|
299
|
+
// If it's an identifier, check if it comes from a bounds check function
|
|
300
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
301
|
+
let current = indexNode;
|
|
302
|
+
// Walk up the AST to find where this variable was assigned
|
|
303
|
+
while (current) {
|
|
304
|
+
// Check if we're in a variable declaration
|
|
305
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.VariableDeclarator &&
|
|
306
|
+
current.id.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
307
|
+
current.id.name === indexNode.name &&
|
|
308
|
+
current.init) {
|
|
309
|
+
const init = current.init;
|
|
310
|
+
// Check if assigned from a bounds check function
|
|
311
|
+
if (init.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
312
|
+
init.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
313
|
+
boundsCheckFunctions.includes(init.callee.name)) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
// Check if assigned from Math.min/max with buffer.length
|
|
317
|
+
if (init.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
318
|
+
init.callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
|
|
319
|
+
init.callee.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
320
|
+
init.callee.object.name === 'Math' &&
|
|
321
|
+
init.callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
322
|
+
(init.callee.property.name === 'min' || init.callee.property.name === 'max')) {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
// Check if it's a parameter in a function - assume validated if it's a function param
|
|
328
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
329
|
+
current.type === eslint_devkit_1.AST_NODE_TYPES.FunctionExpression ||
|
|
330
|
+
current.type === eslint_devkit_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
331
|
+
const params = current.params;
|
|
332
|
+
for (const param of params) {
|
|
333
|
+
if (param.type === eslint_devkit_1.AST_NODE_TYPES.Identifier && param.name === indexNode.name) {
|
|
334
|
+
return true; // Function parameters are assumed validated
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
current = current.parent;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// Check if it's a call to a bounds check function directly
|
|
342
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
343
|
+
indexNode.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
344
|
+
boundsCheckFunctions.includes(indexNode.callee.name)) {
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
return false;
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* Check if there's a bounds check in the current scope
|
|
351
|
+
*/
|
|
352
|
+
const hasBoundsCheck = (bufferName, indexNode) => {
|
|
353
|
+
// Look for bounds checks in the current function scope
|
|
354
|
+
let current = indexNode;
|
|
355
|
+
while (current) {
|
|
356
|
+
// Check if we're in a function
|
|
357
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
358
|
+
current.type === eslint_devkit_1.AST_NODE_TYPES.FunctionExpression ||
|
|
359
|
+
current.type === eslint_devkit_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
// Look for if statements that check bounds
|
|
363
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.IfStatement) {
|
|
364
|
+
const condition = current.test;
|
|
365
|
+
const conditionText = sourceCode.getText(condition).toLowerCase();
|
|
366
|
+
// Check for bounds checking patterns
|
|
367
|
+
if (conditionText.includes(`${bufferName}.length`) &&
|
|
368
|
+
(conditionText.includes('<') || conditionText.includes('<=') ||
|
|
369
|
+
conditionText.includes('>') || conditionText.includes('>=') ||
|
|
370
|
+
conditionText.includes('&&') || conditionText.includes('||'))) {
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Look for variable declarations that might be bounds checks
|
|
375
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.VariableDeclaration) {
|
|
376
|
+
for (const declarator of current.declarations) {
|
|
377
|
+
if (declarator.init) {
|
|
378
|
+
const initText = sourceCode.getText(declarator.init).toLowerCase();
|
|
379
|
+
if (initText.includes(`${bufferName}.length`) &&
|
|
380
|
+
(initText.includes('math.min') || initText.includes('math.max') ||
|
|
381
|
+
initText.includes('mathmin') || initText.includes('mathmax'))) {
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// Look for return statements or early returns that might indicate bounds checking
|
|
388
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.ReturnStatement && current.argument) {
|
|
389
|
+
const returnText = sourceCode.getText(current.argument).toLowerCase();
|
|
390
|
+
if (returnText.includes(`${bufferName}.length`)) {
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
current = current.parent;
|
|
395
|
+
}
|
|
396
|
+
return false;
|
|
397
|
+
};
|
|
398
|
+
/**
|
|
399
|
+
* Check if index could be negative
|
|
400
|
+
*/
|
|
401
|
+
const couldBeNegative = (indexNode) => {
|
|
402
|
+
// Check for literal negative numbers
|
|
403
|
+
// Check for literal negative numbers
|
|
404
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.Literal && typeof indexNode.value === 'number') {
|
|
405
|
+
return indexNode.value < 0;
|
|
406
|
+
}
|
|
407
|
+
// Check for unary minus expressions like -1, -10, etc.
|
|
408
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.UnaryExpression &&
|
|
409
|
+
indexNode.operator === '-' &&
|
|
410
|
+
indexNode.argument.type === eslint_devkit_1.AST_NODE_TYPES.Literal &&
|
|
411
|
+
typeof indexNode.argument.value === 'number') {
|
|
412
|
+
return true; // -N is always negative for positive N
|
|
413
|
+
}
|
|
414
|
+
// Check for binary expressions that could be negative like userInput - 10
|
|
415
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.BinaryExpression && indexNode.operator === '-') {
|
|
416
|
+
// userInput - 10 could be negative, we can't be sure statically
|
|
417
|
+
return true; // Conservative: assume it could be negative
|
|
418
|
+
}
|
|
419
|
+
// For variables, we can't be sure, but we can check for obvious patterns
|
|
420
|
+
if (indexNode.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
421
|
+
// Check if this variable is assigned a negative value somewhere
|
|
422
|
+
// This is a simplified check - in practice we'd need more sophisticated analysis
|
|
423
|
+
let current = indexNode;
|
|
424
|
+
while (current) {
|
|
425
|
+
if (current.type === eslint_devkit_1.AST_NODE_TYPES.VariableDeclarator && current.init) {
|
|
426
|
+
if (current.init.type === eslint_devkit_1.AST_NODE_TYPES.Literal &&
|
|
427
|
+
typeof current.init.value === 'number' &&
|
|
428
|
+
current.init.value < 0) {
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
// Check for unary minus assignments
|
|
432
|
+
if (current.init.type === eslint_devkit_1.AST_NODE_TYPES.UnaryExpression &&
|
|
433
|
+
current.init.operator === '-' &&
|
|
434
|
+
current.init.argument.type === eslint_devkit_1.AST_NODE_TYPES.Literal &&
|
|
435
|
+
typeof current.init.argument.value === 'number') {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
current = current.parent;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
};
|
|
444
|
+
return {
|
|
445
|
+
// Track buffer variable declarations
|
|
446
|
+
VariableDeclarator(node) {
|
|
447
|
+
if (node.id.type === eslint_devkit_1.AST_NODE_TYPES.Identifier && node.init) {
|
|
448
|
+
const varName = node.id.name;
|
|
449
|
+
// Check if assigned a buffer type
|
|
450
|
+
if (node.init.type === eslint_devkit_1.AST_NODE_TYPES.NewExpression &&
|
|
451
|
+
node.init.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
452
|
+
bufferTypes.includes(node.init.callee.name)) {
|
|
453
|
+
bufferVars.add(varName);
|
|
454
|
+
}
|
|
455
|
+
// Check if assigned from Buffer.from() or Buffer.alloc()
|
|
456
|
+
if (node.init.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
457
|
+
node.init.callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
|
|
458
|
+
node.init.callee.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
459
|
+
node.init.callee.object.name === 'Buffer' &&
|
|
460
|
+
node.init.callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
461
|
+
['from', 'alloc', 'allocUnsafe'].includes(node.init.callee.property.name)) {
|
|
462
|
+
bufferVars.add(varName);
|
|
463
|
+
}
|
|
464
|
+
// Check if assigned a buffer method result
|
|
465
|
+
if (node.init.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression) {
|
|
466
|
+
const callee = node.init.callee;
|
|
467
|
+
if (callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
|
|
468
|
+
callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
469
|
+
bufferMethods.includes(callee.property.name)) {
|
|
470
|
+
bufferVars.add(varName);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
// Check variable name patterns
|
|
474
|
+
if (bufferTypes.some(type => varName.toLowerCase().includes(type.toLowerCase()))) {
|
|
475
|
+
bufferVars.add(varName);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
// Check member expressions (buffer[index], buffer.method())
|
|
480
|
+
MemberExpression(node) {
|
|
481
|
+
// Check for buffer[index] access
|
|
482
|
+
if (node.computed && node.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
483
|
+
const bufferName = node.object.name;
|
|
484
|
+
const indexNode = node.property;
|
|
485
|
+
if (isBufferType(bufferName)) {
|
|
486
|
+
// Check for negative indices
|
|
487
|
+
if (couldBeNegative(indexNode)) {
|
|
488
|
+
context.report({
|
|
489
|
+
node,
|
|
490
|
+
messageId: 'negativeBufferIndex',
|
|
491
|
+
data: {
|
|
492
|
+
filePath: filename,
|
|
493
|
+
line: String(node.loc?.start.line ?? 0),
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
// Check for user-controlled indices without validation
|
|
499
|
+
if (isUserControlledIndex(indexNode) && !isIndexValidated(indexNode)) {
|
|
500
|
+
// Check if there's a bounds check in scope
|
|
501
|
+
if (!hasBoundsCheck(bufferName, indexNode)) {
|
|
502
|
+
/* c8 ignore start -- safetyChecker.isSafe requires JSDoc annotations not testable via RuleTester */
|
|
503
|
+
if (safetyChecker.isSafe(node, context)) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
/* c8 ignore stop */
|
|
507
|
+
context.report({
|
|
508
|
+
node,
|
|
509
|
+
messageId: 'userControlledBufferIndex',
|
|
510
|
+
data: {
|
|
511
|
+
filePath: filename,
|
|
512
|
+
line: String(node.loc?.start.line ?? 0),
|
|
513
|
+
},
|
|
514
|
+
});
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// Check if there's any bounds validation
|
|
519
|
+
if (!hasBoundsCheck(bufferName, indexNode) && !isIndexValidated(indexNode)) {
|
|
520
|
+
/* c8 ignore start -- safetyChecker.isSafe requires JSDoc annotations not testable via RuleTester */
|
|
521
|
+
if (safetyChecker.isSafe(node, context)) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
/* c8 ignore stop */
|
|
525
|
+
context.report({
|
|
526
|
+
node,
|
|
527
|
+
messageId: 'unsafeBufferAccess',
|
|
528
|
+
data: {
|
|
529
|
+
filePath: filename,
|
|
530
|
+
line: String(node.loc?.start.line ?? 0),
|
|
531
|
+
},
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
// Check for buffer method calls that need bounds checking
|
|
537
|
+
if (node.property.type === 'Identifier' &&
|
|
538
|
+
bufferMethods.includes(node.property.name) &&
|
|
539
|
+
node.object.type === 'Identifier' &&
|
|
540
|
+
isBufferType(node.object.name)) {
|
|
541
|
+
// This is a parent of a CallExpression, we'll check it there
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
// Check buffer method calls
|
|
545
|
+
CallExpression(node) {
|
|
546
|
+
const callee = node.callee;
|
|
547
|
+
// Check for buffer.slice() calls
|
|
548
|
+
if (callee.type === 'MemberExpression' &&
|
|
549
|
+
callee.property.type === 'Identifier' &&
|
|
550
|
+
callee.property.name === 'slice' &&
|
|
551
|
+
callee.object.type === 'Identifier' &&
|
|
552
|
+
isBufferType(callee.object.name)) {
|
|
553
|
+
const args = node.arguments;
|
|
554
|
+
// Check slice arguments
|
|
555
|
+
for (const arg of args) {
|
|
556
|
+
if (isUserControlledIndex(arg) && !isIndexValidated(arg)) {
|
|
557
|
+
/* c8 ignore start -- safetyChecker.isSafe requires JSDoc annotations not testable via RuleTester */
|
|
558
|
+
if (safetyChecker.isSafe(node, context)) {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
/* c8 ignore stop */
|
|
562
|
+
context.report({
|
|
563
|
+
node: arg,
|
|
564
|
+
messageId: 'unsafeBufferSlice',
|
|
565
|
+
data: {
|
|
566
|
+
filePath: filename,
|
|
567
|
+
line: String(node.loc?.start.line ?? 0),
|
|
568
|
+
},
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// Check for buffer read/write methods
|
|
574
|
+
if (callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
|
|
575
|
+
callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
576
|
+
bufferMethods.includes(callee.property.name) &&
|
|
577
|
+
callee.object.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
578
|
+
isBufferType(callee.object.name)) {
|
|
579
|
+
const args = node.arguments;
|
|
580
|
+
// Check offset/length arguments
|
|
581
|
+
for (const arg of args) {
|
|
582
|
+
if (isUserControlledIndex(arg) && !isIndexValidated(arg)) {
|
|
583
|
+
/* c8 ignore start -- safetyChecker.isSafe requires JSDoc annotations not testable via RuleTester */
|
|
584
|
+
if (safetyChecker.isSafe(node, context)) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
/* c8 ignore stop */
|
|
588
|
+
context.report({
|
|
589
|
+
node: arg,
|
|
590
|
+
messageId: 'missingBoundsCheck',
|
|
591
|
+
data: {
|
|
592
|
+
filePath: filename,
|
|
593
|
+
line: String(node.loc?.start.line ?? 0),
|
|
594
|
+
},
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
// Check binary expressions that might involve buffer operations
|
|
601
|
+
BinaryExpression(node) {
|
|
602
|
+
// Look for patterns like buffer.length - something that might indicate bounds checking
|
|
603
|
+
const leftText = sourceCode.getText(node.left);
|
|
604
|
+
const rightText = sourceCode.getText(node.right);
|
|
605
|
+
if (leftText.includes('.length') || rightText.includes('.length')) {
|
|
606
|
+
// This might be a bounds check - we could analyze this further
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-node-security/src/rules/no-buffer-overread/index.ts"],"names":[],"mappings":"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"}
|