eslint-plugin-secure-coding 2.3.4 → 2.4.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +3 -2
  3. package/package.json +2 -9
  4. package/src/index.d.ts +1 -1
  5. package/src/index.js +0 -49
  6. package/src/types/index.d.ts +4 -29
  7. package/src/types/index.js +3 -4
  8. package/src/rules/database-injection/index.d.ts +0 -13
  9. package/src/rules/database-injection/index.js +0 -406
  10. package/src/rules/no-credentials-in-storage-api/index.d.ts +0 -6
  11. package/src/rules/no-credentials-in-storage-api/index.js +0 -54
  12. package/src/rules/no-document-cookie/index.d.ts +0 -5
  13. package/src/rules/no-document-cookie/index.js +0 -89
  14. package/src/rules/no-insecure-cookie-settings/index.d.ts +0 -9
  15. package/src/rules/no-insecure-cookie-settings/index.js +0 -306
  16. package/src/rules/no-insecure-jwt/index.d.ts +0 -10
  17. package/src/rules/no-insecure-jwt/index.js +0 -380
  18. package/src/rules/no-insufficient-postmessage-validation/index.d.ts +0 -14
  19. package/src/rules/no-insufficient-postmessage-validation/index.js +0 -392
  20. package/src/rules/no-insufficient-random/index.d.ts +0 -9
  21. package/src/rules/no-insufficient-random/index.js +0 -208
  22. package/src/rules/no-postmessage-origin-wildcard/index.d.ts +0 -8
  23. package/src/rules/no-postmessage-origin-wildcard/index.js +0 -56
  24. package/src/rules/no-sql-injection/index.d.ts +0 -10
  25. package/src/rules/no-sql-injection/index.js +0 -335
  26. package/src/rules/no-timing-attack/index.d.ts +0 -10
  27. package/src/rules/no-timing-attack/index.js +0 -447
  28. package/src/rules/no-unencrypted-local-storage/index.d.ts +0 -8
  29. package/src/rules/no-unencrypted-local-storage/index.js +0 -61
  30. package/src/rules/no-unsanitized-html/index.d.ts +0 -9
  31. package/src/rules/no-unsanitized-html/index.js +0 -335
  32. package/src/rules/no-weak-crypto/index.d.ts +0 -11
  33. package/src/rules/no-weak-crypto/index.js +0 -351
@@ -1,406 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.databaseInjection = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- exports.databaseInjection = (0, eslint_devkit_2.createRule)({
7
- name: 'database-injection',
8
- meta: {
9
- type: 'problem',
10
- docs: {
11
- description: 'Detects SQL and NoSQL injection vulnerabilities with framework-specific fixes',
12
- },
13
- messages: (() => {
14
- const databaseInjection = (0, eslint_devkit_1.formatLLMMessage)({
15
- icon: eslint_devkit_1.MessageIcons.SECURITY,
16
- issueName: 'SQL Injection',
17
- cwe: 'CWE-89',
18
- description: 'SQL Injection detected',
19
- severity: 'CRITICAL',
20
- fix: 'Use parameterized query: db.query("SELECT * FROM users WHERE id = ?", [userId])',
21
- documentationLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
22
- });
23
- const usePrisma = (0, eslint_devkit_1.formatLLMMessage)({
24
- icon: eslint_devkit_1.MessageIcons.INFO,
25
- issueName: 'Use Prisma',
26
- description: 'Use Prisma ORM',
27
- severity: 'LOW',
28
- fix: 'await prisma.user.findMany({ where: { id } })',
29
- documentationLink: 'https://www.prisma.io/docs',
30
- });
31
- const useTypeORM = (0, eslint_devkit_1.formatLLMMessage)({
32
- icon: eslint_devkit_1.MessageIcons.INFO,
33
- issueName: 'Use TypeORM',
34
- description: 'Use TypeORM with QueryBuilder',
35
- severity: 'LOW',
36
- fix: 'userRepository.createQueryBuilder().where("id = :id", { id })',
37
- documentationLink: 'https://typeorm.io/',
38
- });
39
- const useParameterized = (0, eslint_devkit_1.formatLLMMessage)({
40
- icon: eslint_devkit_1.MessageIcons.INFO,
41
- issueName: 'Use Parameterized',
42
- description: 'Use parameterized query',
43
- severity: 'LOW',
44
- fix: 'db.query("SELECT * FROM users WHERE id = ?", [userId])',
45
- documentationLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
46
- });
47
- const useMongoSanitize = (0, eslint_devkit_1.formatLLMMessage)({
48
- icon: eslint_devkit_1.MessageIcons.INFO,
49
- issueName: 'Use mongo-sanitize',
50
- description: 'Use mongo-sanitize for MongoDB',
51
- severity: 'LOW',
52
- fix: 'sanitize(req.body)',
53
- documentationLink: 'https://github.com/vkarpov15/mongo-sanitize',
54
- });
55
- const strategyParameterize = (0, eslint_devkit_1.formatLLMMessage)({
56
- icon: eslint_devkit_1.MessageIcons.STRATEGY,
57
- issueName: 'Parameterize Strategy',
58
- description: 'Use parameterized queries',
59
- severity: 'LOW',
60
- fix: 'Use ? or :name placeholders for user input',
61
- documentationLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
62
- });
63
- const strategyORM = (0, eslint_devkit_1.formatLLMMessage)({
64
- icon: eslint_devkit_1.MessageIcons.STRATEGY,
65
- issueName: 'ORM Strategy',
66
- description: 'Migrate to ORM for automatic protection',
67
- severity: 'LOW',
68
- fix: 'Use Prisma, TypeORM, or Sequelize',
69
- documentationLink: 'https://www.prisma.io/docs/concepts/overview/why-prisma',
70
- });
71
- const strategySanitize = (0, eslint_devkit_1.formatLLMMessage)({
72
- icon: eslint_devkit_1.MessageIcons.STRATEGY,
73
- issueName: 'Sanitize Strategy',
74
- description: 'Add input sanitization',
75
- severity: 'LOW',
76
- fix: 'Sanitize input as last resort',
77
- documentationLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
78
- });
79
- const strategyAuto = (0, eslint_devkit_1.formatLLMMessage)({
80
- icon: eslint_devkit_1.MessageIcons.STRATEGY,
81
- issueName: 'Auto Strategy',
82
- description: 'Apply context-aware injection prevention',
83
- severity: 'LOW',
84
- fix: 'Use context-appropriate protection',
85
- documentationLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
86
- });
87
- return {
88
- databaseInjection,
89
- usePrisma,
90
- useTypeORM,
91
- useParameterized,
92
- useMongoSanitize,
93
- strategyParameterize,
94
- strategyORM,
95
- strategySanitize,
96
- strategyAuto,
97
- };
98
- })(),
99
- schema: [
100
- {
101
- type: 'object',
102
- properties: {
103
- detectNoSQL: {
104
- type: 'boolean',
105
- default: true,
106
- },
107
- detectORMs: {
108
- type: 'boolean',
109
- default: true,
110
- description: 'Detect unsafe ORM usage',
111
- },
112
- trustedSources: {
113
- type: 'array',
114
- items: { type: 'string' },
115
- default: [],
116
- },
117
- frameworkHints: {
118
- type: 'boolean',
119
- default: true,
120
- description: 'Provide framework-specific suggestions',
121
- },
122
- strategy: {
123
- type: 'string',
124
- enum: ['parameterize', 'orm', 'sanitize', 'auto'],
125
- default: 'auto',
126
- description: 'Strategy for fixing injection (auto = smart detection)'
127
- },
128
- },
129
- additionalProperties: false,
130
- },
131
- ],
132
- },
133
- defaultOptions: [
134
- {
135
- detectNoSQL: true,
136
- detectORMs: true,
137
- trustedSources: [],
138
- frameworkHints: true,
139
- strategy: 'auto',
140
- },
141
- ],
142
- create(context) {
143
- const options = context.options[0] || {};
144
- const { detectNoSQL = true, strategy = 'auto' } = options || {};
145
- const sourceCode = context.sourceCode || context.sourceCode;
146
- /**
147
- * Select message ID based on strategy
148
- * @todo Consider using this for suggestions in future versions
149
- */
150
- const selectStrategyMessage = () => {
151
- switch (strategy) {
152
- case 'parameterize':
153
- return 'strategyParameterize';
154
- case 'orm':
155
- return 'strategyORM';
156
- case 'sanitize':
157
- return 'strategySanitize';
158
- case 'auto':
159
- default:
160
- // Auto mode: prefer parameterized queries
161
- return 'useParameterized';
162
- }
163
- };
164
- const filename = context.filename || context.getFilename();
165
- /**
166
- * SQL keywords for detection
167
- */
168
- const SQL_KEYWORDS = [
169
- 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER',
170
- 'EXEC', 'EXECUTE', 'TRUNCATE', 'GRANT', 'REVOKE', 'WHERE', 'FROM', 'JOIN'
171
- ];
172
- /**
173
- * NoSQL patterns
174
- */
175
- const NOSQL_PATTERNS = [
176
- 'find', 'findOne', 'findById', 'updateOne', 'updateMany', 'deleteOne',
177
- 'deleteMany', 'aggregate', '$where', '$regex'
178
- ];
179
- /**
180
- * NoSQL query patterns in template literals (e.g., `this.name === "${userName}"`)
181
- */
182
- const NOSQL_QUERY_PATTERNS = [
183
- /this\.\w+\s*===?\s*["']/i, // this.name === "value"
184
- /this\.\w+\s*!==?\s*["']/i, // this.name !== "value"
185
- /\$\w+\s*===?\s*["']/i, // $where === "value"
186
- ];
187
- /**
188
- * Check if text contains SQL keywords
189
- */
190
- function containsSQLKeywords(text) {
191
- const upperText = text.toUpperCase();
192
- return SQL_KEYWORDS.some(keyword => upperText.includes(keyword));
193
- }
194
- /**
195
- * Check if code is using NoSQL operations
196
- */
197
- function isNoSQLOperation(node) {
198
- const text = sourceCode.getText(node);
199
- return NOSQL_PATTERNS.some(pattern => text.includes(pattern));
200
- }
201
- /**
202
- * Check if expression is tainted (contains user input)
203
- */
204
- function isTainted(node) {
205
- const text = sourceCode.getText(node);
206
- const { trustedSources = [] } = options;
207
- // High confidence taint sources
208
- const highConfidenceSources = [
209
- 'req.body', 'req.query', 'req.params', 'request.body',
210
- 'params.', 'query.', 'body.', 'input.', 'userInput'
211
- ];
212
- // Medium confidence taint sources
213
- const mediumConfidenceSources = [
214
- 'props.', 'state.', 'context.', 'event.', 'data.'
215
- ];
216
- for (const source of highConfidenceSources) {
217
- if (text.includes(source)) {
218
- return { tainted: true, source, confidence: 'high' };
219
- }
220
- }
221
- for (const source of mediumConfidenceSources) {
222
- if (text.includes(source)) {
223
- return { tainted: true, source, confidence: 'medium' };
224
- }
225
- }
226
- // Check if this source is explicitly trusted (only for low-confidence sources)
227
- for (const trusted of trustedSources) {
228
- if (text.includes(trusted)) {
229
- return { tainted: false, confidence: 'low' };
230
- }
231
- }
232
- // Check if it's a variable (low confidence)
233
- if (node.type === 'Identifier' && !text.match(/^[A-Z_]+$/)) {
234
- return { tainted: true, source: 'variable', confidence: 'low' };
235
- }
236
- return { tainted: false, confidence: 'low' };
237
- }
238
- /**
239
- * Analyze vulnerability and provide detailed report
240
- */
241
- function analyzeVulnerability(node, vulnType) {
242
- const taintInfo = isTainted(node);
243
- return {
244
- type: vulnType,
245
- pattern: taintInfo.tainted
246
- ? `User input (${taintInfo.source}) in query`
247
- : 'Dynamic query construction',
248
- severity: taintInfo.confidence === 'high' ? 'critical' : taintInfo.confidence === 'medium' ? 'high' : 'medium',
249
- exploitability: taintInfo.confidence === 'high'
250
- ? 'Easily exploitable via API parameters'
251
- : 'Exploitable with access to input sources',
252
- cwe: vulnType === 'SQL' ? 'CWE-89' : 'CWE-943',
253
- owasp: 'A03:2021 - Injection',
254
- };
255
- }
256
- /**
257
- * Report additional strategy-specific suggestions
258
- */
259
- function reportStrategySuggestions(node) {
260
- const strategyMessageId = selectStrategyMessage();
261
- if (strategyMessageId !== 'useParameterized') { // Don't duplicate the main message
262
- context.report({
263
- node,
264
- messageId: strategyMessageId,
265
- });
266
- }
267
- }
268
- /**
269
- * Check template literal for SQL or NoSQL injection
270
- */
271
- function checkTemplateLiteral(node) {
272
- const text = sourceCode.getText(node);
273
- // Check for SQL injection
274
- if (containsSQLKeywords(text) && node.expressions.length > 0) {
275
- // Check if any expression is tainted
276
- const taintedExprs = node.expressions.filter((expr) => isTainted(expr).tainted);
277
- if (taintedExprs.length > 0) {
278
- const vulnDetails = analyzeVulnerability(node, 'SQL');
279
- const data = {
280
- type: vulnDetails.type,
281
- severity: vulnDetails.severity.toUpperCase(),
282
- filePath: filename,
283
- line: String(node.loc?.start.line ?? 0),
284
- cwe: vulnDetails.cwe,
285
- cweCode: vulnDetails.cwe.replace('CWE-', ''),
286
- currentExample: `db.query(\`SELECT * FROM users WHERE id = ${'${userId}'}\`)`,
287
- fixExample: `Use parameterized: db.query("SELECT * FROM users WHERE id = ?", [userId])`,
288
- docLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
289
- };
290
- context.report({
291
- node,
292
- messageId: 'databaseInjection',
293
- data,
294
- });
295
- reportStrategySuggestions(node);
296
- return;
297
- }
298
- }
299
- // Check for NoSQL injection patterns in template literals
300
- if (detectNoSQL && node.expressions.length > 0) {
301
- const hasNoSQLPattern = NOSQL_QUERY_PATTERNS.some(pattern => pattern.test(text));
302
- if (hasNoSQLPattern) {
303
- // Check if any expression is tainted
304
- const taintedExprs = node.expressions.filter((expr) => isTainted(expr).tainted);
305
- if (taintedExprs.length > 0) {
306
- const vulnDetails = analyzeVulnerability(node, 'NoSQL');
307
- const data = {
308
- type: vulnDetails.type,
309
- severity: vulnDetails.severity.toUpperCase(),
310
- filePath: filename,
311
- line: String(node.loc?.start.line ?? 0),
312
- cwe: vulnDetails.cwe,
313
- cweCode: vulnDetails.cwe.replace('CWE-', ''),
314
- currentExample: `const query = \`this.name === "${'${userName}'}"\``,
315
- fixExample: `Sanitize input: const query = \`this.name === "\${mongoSanitize(userName)}"\``,
316
- docLink: 'https://owasp.org/www-community/attacks/NoSQL_Injection',
317
- };
318
- context.report({
319
- node,
320
- messageId: 'databaseInjection',
321
- data,
322
- });
323
- reportStrategySuggestions(node);
324
- return;
325
- }
326
- }
327
- }
328
- }
329
- /**
330
- * Check NoSQL operations
331
- */
332
- function checkNoSQLOperation(node) {
333
- if (!detectNoSQL)
334
- return;
335
- if (!isNoSQLOperation(node))
336
- return;
337
- // Check if arguments contain user input
338
- const taintedArgs = node.arguments.filter((arg) => isTainted(arg).tainted);
339
- if (taintedArgs.length === 0)
340
- return;
341
- const vulnDetails = analyzeVulnerability(node, 'NoSQL');
342
- const data = {
343
- type: vulnDetails.type,
344
- severity: vulnDetails.severity.toUpperCase(),
345
- filePath: filename,
346
- line: String(node.loc?.start.line ?? 0),
347
- cwe: vulnDetails.cwe,
348
- cweCode: vulnDetails.cwe.replace('CWE-', ''),
349
- currentExample: `User.findOne({ email: req.body.email })`,
350
- fixExample: `Sanitize input: User.findOne({ email: mongoSanitize(req.body.email) })`,
351
- docLink: 'https://owasp.org/www-community/attacks/NoSQL_Injection',
352
- };
353
- context.report({
354
- node,
355
- messageId: 'databaseInjection',
356
- data,
357
- });
358
- reportStrategySuggestions(node);
359
- }
360
- /**
361
- * Check binary expression (string concatenation) for SQL injection
362
- */
363
- function checkBinaryExpression(node) {
364
- // Only check string concatenation with + operator
365
- if (node.operator !== '+')
366
- return;
367
- // Get the full text of the binary expression
368
- const text = sourceCode.getText(node);
369
- // Check if it contains SQL keywords
370
- if (!containsSQLKeywords(text))
371
- return;
372
- // Check if any part of the expression is tainted
373
- const taintInfo = isTainted(node);
374
- if (!taintInfo.tainted) {
375
- // Also check left and right sides individually
376
- const leftTainted = isTainted(node.left).tainted;
377
- const rightTainted = isTainted(node.right).tainted;
378
- if (!leftTainted && !rightTainted)
379
- return;
380
- }
381
- const vulnDetails = analyzeVulnerability(node, 'SQL');
382
- const data = {
383
- type: vulnDetails.type,
384
- severity: vulnDetails.severity.toUpperCase(),
385
- filePath: filename,
386
- line: String(node.loc?.start.line ?? 0),
387
- cwe: vulnDetails.cwe,
388
- cweCode: vulnDetails.cwe.replace('CWE-', ''),
389
- currentExample: `const query = "SELECT * FROM users WHERE name = '" + userName + "'"`,
390
- fixExample: `Use parameterized: db.query("SELECT * FROM users WHERE name = ?", [userName])`,
391
- docLink: 'https://owasp.org/www-community/attacks/SQL_Injection',
392
- };
393
- context.report({
394
- node,
395
- messageId: 'databaseInjection',
396
- data,
397
- });
398
- reportStrategySuggestions(node);
399
- }
400
- return {
401
- TemplateLiteral: checkTemplateLiteral,
402
- CallExpression: checkNoSQLOperation,
403
- BinaryExpression: checkBinaryExpression,
404
- };
405
- },
406
- });
@@ -1,6 +0,0 @@
1
- /**
2
- * @fileoverview Disallow storing credentials in browser/mobile storage APIs
3
- */
4
- export interface Options {
5
- }
6
- export declare const noCredentialsInStorageApi: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -1,54 +0,0 @@
1
- "use strict";
2
- /**
3
- * @fileoverview Disallow storing credentials in browser/mobile storage APIs
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.noCredentialsInStorageApi = void 0;
7
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
8
- exports.noCredentialsInStorageApi = (0, eslint_devkit_1.createRule)({
9
- name: 'no-credentials-in-storage-api',
10
- meta: {
11
- type: 'problem',
12
- docs: {
13
- description: 'Disallow storing credentials in browser/mobile storage APIs',
14
- },
15
- messages: {
16
- violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
17
- icon: eslint_devkit_1.MessageIcons.SECURITY,
18
- issueName: 'Credentials in Storage',
19
- cwe: 'CWE-522',
20
- description: 'Credentials stored in insecure browser/mobile storage',
21
- severity: 'CRITICAL',
22
- fix: 'Use secure storage like Keychain, SecureStore, or encrypted storage',
23
- documentationLink: 'https://cwe.mitre.org/data/definitions/522.html',
24
- })
25
- },
26
- schema: [],
27
- },
28
- defaultOptions: [],
29
- create(context) {
30
- function report(node) {
31
- context.report({ node, messageId: 'violationDetected' });
32
- }
33
- const sensitiveKeys = ['password', 'token', 'apikey', 'secret', 'credential', 'auth', 'key'];
34
- const storageObjects = ['localStorage', 'sessionStorage', 'AsyncStorage'];
35
- return {
36
- CallExpression(node) {
37
- // Check localStorage.setItem/sessionStorage.setItem/AsyncStorage.setItem
38
- if (node.callee.type === 'MemberExpression' &&
39
- node.callee.object.type === 'Identifier' &&
40
- storageObjects.includes(node.callee.object.name) &&
41
- node.callee.property.type === 'Identifier' &&
42
- node.callee.property.name === 'setItem') {
43
- const keyArg = node.arguments[0];
44
- if (keyArg && keyArg.type === 'Literal' && typeof keyArg.value === 'string') {
45
- const key = keyArg.value.toLowerCase();
46
- if (sensitiveKeys.some(k => key.includes(k))) {
47
- report(node);
48
- }
49
- }
50
- }
51
- },
52
- };
53
- },
54
- });
@@ -1,5 +0,0 @@
1
- export interface Options {
2
- /** Allow reading document.cookie for parsing */
3
- allowReading?: boolean;
4
- }
5
- export declare const noDocumentCookie: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noDocumentCookie = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- exports.noDocumentCookie = (0, eslint_devkit_1.createRule)({
7
- name: 'no-document-cookie',
8
- meta: {
9
- type: 'problem',
10
- docs: {
11
- description: 'Prevent direct usage of document.cookie - use Cookie Store API or cookie libraries instead',
12
- },
13
- hasSuggestions: false,
14
- messages: {
15
- noDocumentCookie: (0, eslint_devkit_2.formatLLMMessage)({
16
- icon: eslint_devkit_2.MessageIcons.WARNING,
17
- issueName: 'Document Cookie',
18
- description: 'Avoid direct document.cookie usage',
19
- severity: 'MEDIUM',
20
- fix: 'Use Cookie Store API or cookie library instead',
21
- documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-document-cookie.md',
22
- }),
23
- },
24
- schema: [
25
- {
26
- type: 'object',
27
- properties: {
28
- allowReading: {
29
- type: 'boolean',
30
- default: true,
31
- },
32
- },
33
- additionalProperties: false,
34
- },
35
- ],
36
- },
37
- defaultOptions: [{ allowReading: true }],
38
- create(context) {
39
- const [options] = context.options;
40
- const { allowReading = true } = options || {};
41
- function isDocumentCookieAccess(node) {
42
- // Check if this is accessing document.cookie
43
- return (node.object.type === 'Identifier' &&
44
- node.object.name === 'document' &&
45
- ((node.property.type === 'Identifier' && node.property.name === 'cookie') ||
46
- (node.computed && node.property.type === 'Literal' && node.property.value === 'cookie')));
47
- }
48
- function isAssignmentToCookie(node) {
49
- // Check if this is an assignment to document.cookie
50
- const parent = node.parent;
51
- // Check direct assignment
52
- if (parent?.type === 'AssignmentExpression' && parent.left === node) {
53
- return true;
54
- }
55
- // Check compound assignment (+=, -=, etc.)
56
- if (parent?.type === 'AssignmentExpression' &&
57
- parent.operator &&
58
- parent.operator.includes('=') &&
59
- parent.left === node) {
60
- return true;
61
- }
62
- // Variable declarator (const/let/var x = document.cookie) - this is reading, not assigning
63
- if (parent?.type === 'VariableDeclarator' && parent.init === node) {
64
- return false;
65
- }
66
- return false;
67
- }
68
- return {
69
- MemberExpression(node) {
70
- if (isDocumentCookieAccess(node)) {
71
- const isAssigning = isAssignmentToCookie(node);
72
- // If allowReading is true, only flag assignments
73
- // If allowReading is false, flag everything
74
- if (allowReading && !isAssigning) {
75
- return; // Allow reading when option is enabled
76
- }
77
- // Flag document.cookie usage
78
- context.report({
79
- node,
80
- messageId: 'noDocumentCookie',
81
- data: {
82
- operation: isAssigning ? 'assignment to' : 'reading from',
83
- },
84
- });
85
- }
86
- },
87
- };
88
- },
89
- });
@@ -1,9 +0,0 @@
1
- export interface Options {
2
- /** Allow insecure cookies in test files. Default: false */
3
- allowInTests?: boolean;
4
- /** Cookie library patterns to recognize. Default: ['cookie', 'js-cookie', 'universal-cookie'] */
5
- cookieLibraries?: string[];
6
- /** Additional safe patterns to ignore. Default: [] */
7
- ignorePatterns?: string[];
8
- }
9
- export declare const noInsecureCookieSettings: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;