eslint-plugin-secure-coding 3.0.0 → 3.0.2

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 (158) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +1 -1
  3. package/README.md +90 -422
  4. package/package.json +6 -5
  5. package/src/index.d.ts +5 -14
  6. package/src/index.js +36 -265
  7. package/src/rules/detect-non-literal-regexp/index.d.ts +20 -1
  8. package/src/rules/detect-non-literal-regexp/index.js +5 -0
  9. package/src/rules/detect-object-injection/index.d.ts +25 -1
  10. package/src/rules/detect-object-injection/index.js +5 -0
  11. package/src/rules/detect-weak-password-validation/index.d.ts +8 -2
  12. package/src/rules/detect-weak-password-validation/index.js +6 -1
  13. package/src/rules/no-directive-injection/index.d.ts +27 -1
  14. package/src/rules/no-directive-injection/index.js +5 -0
  15. package/src/rules/no-electron-security-issues/index.d.ts +27 -1
  16. package/src/rules/no-electron-security-issues/index.js +5 -0
  17. package/src/rules/no-format-string-injection/index.d.ts +28 -1
  18. package/src/rules/no-format-string-injection/index.js +5 -0
  19. package/src/rules/no-graphql-injection/index.d.ts +29 -1
  20. package/src/rules/no-graphql-injection/index.js +5 -0
  21. package/src/rules/no-hardcoded-credentials/index.d.ts +19 -1
  22. package/src/rules/no-hardcoded-credentials/index.js +5 -0
  23. package/src/rules/no-hardcoded-session-tokens/index.d.ts +8 -2
  24. package/src/rules/no-hardcoded-session-tokens/index.js +6 -1
  25. package/src/rules/no-improper-sanitization/index.d.ts +27 -1
  26. package/src/rules/no-improper-sanitization/index.js +5 -0
  27. package/src/rules/no-improper-type-validation/index.d.ts +27 -1
  28. package/src/rules/no-improper-type-validation/index.js +5 -0
  29. package/src/rules/no-insecure-comparison/index.d.ts +20 -1
  30. package/src/rules/no-insecure-comparison/index.js +5 -0
  31. package/src/rules/no-ldap-injection/index.d.ts +30 -1
  32. package/src/rules/no-ldap-injection/index.js +5 -0
  33. package/src/rules/no-missing-authentication/index.d.ts +20 -1
  34. package/src/rules/no-missing-authentication/index.js +5 -1
  35. package/src/rules/no-pii-in-logs/index.d.ts +8 -4
  36. package/src/rules/no-pii-in-logs/index.js +15 -12
  37. package/src/rules/no-privilege-escalation/index.d.ts +20 -1
  38. package/src/rules/no-privilege-escalation/index.js +5 -0
  39. package/src/rules/no-redos-vulnerable-regex/index.d.ts +22 -1
  40. package/src/rules/no-redos-vulnerable-regex/index.js +5 -0
  41. package/src/rules/no-sensitive-data-exposure/index.d.ts +20 -1
  42. package/src/rules/no-sensitive-data-exposure/index.js +5 -0
  43. package/src/rules/no-unchecked-loop-condition/index.d.ts +27 -1
  44. package/src/rules/no-unchecked-loop-condition/index.js +5 -0
  45. package/src/rules/no-unlimited-resource-allocation/index.d.ts +27 -1
  46. package/src/rules/no-unlimited-resource-allocation/index.js +5 -0
  47. package/src/rules/no-unsafe-deserialization/index.d.ts +31 -1
  48. package/src/rules/no-unsafe-deserialization/index.js +5 -0
  49. package/src/rules/no-unsafe-regex-construction/index.d.ts +22 -1
  50. package/src/rules/no-unsafe-regex-construction/index.js +5 -0
  51. package/src/rules/no-weak-password-recovery/index.d.ts +27 -1
  52. package/src/rules/no-weak-password-recovery/index.js +5 -0
  53. package/src/rules/no-xpath-injection/index.d.ts +30 -1
  54. package/src/rules/no-xpath-injection/index.js +5 -0
  55. package/src/rules/no-xxe-injection/index.d.ts +30 -1
  56. package/src/rules/no-xxe-injection/index.js +5 -0
  57. package/src/rules/require-backend-authorization/index.d.ts +8 -2
  58. package/src/rules/require-backend-authorization/index.js +6 -1
  59. package/src/rules/require-secure-defaults/index.d.ts +8 -4
  60. package/src/rules/require-secure-defaults/index.js +7 -6
  61. package/src/types/index.d.ts +10 -52
  62. package/src/types/index.js +3 -12
  63. package/src/rules/detect-child-process/index.d.ts +0 -11
  64. package/src/rules/detect-child-process/index.js +0 -529
  65. package/src/rules/detect-eval-with-expression/index.d.ts +0 -9
  66. package/src/rules/detect-eval-with-expression/index.js +0 -392
  67. package/src/rules/detect-mixed-content/index.d.ts +0 -8
  68. package/src/rules/detect-mixed-content/index.js +0 -44
  69. package/src/rules/detect-non-literal-fs-filename/index.d.ts +0 -7
  70. package/src/rules/detect-non-literal-fs-filename/index.js +0 -454
  71. package/src/rules/detect-suspicious-dependencies/index.d.ts +0 -8
  72. package/src/rules/detect-suspicious-dependencies/index.js +0 -71
  73. package/src/rules/no-allow-arbitrary-loads/index.d.ts +0 -8
  74. package/src/rules/no-allow-arbitrary-loads/index.js +0 -47
  75. package/src/rules/no-arbitrary-file-access/index.d.ts +0 -13
  76. package/src/rules/no-arbitrary-file-access/index.js +0 -195
  77. package/src/rules/no-buffer-overread/index.d.ts +0 -29
  78. package/src/rules/no-buffer-overread/index.js +0 -606
  79. package/src/rules/no-clickjacking/index.d.ts +0 -10
  80. package/src/rules/no-clickjacking/index.js +0 -396
  81. package/src/rules/no-client-side-auth-logic/index.d.ts +0 -6
  82. package/src/rules/no-client-side-auth-logic/index.js +0 -69
  83. package/src/rules/no-credentials-in-query-params/index.d.ts +0 -8
  84. package/src/rules/no-credentials-in-query-params/index.js +0 -57
  85. package/src/rules/no-data-in-temp-storage/index.d.ts +0 -6
  86. package/src/rules/no-data-in-temp-storage/index.js +0 -64
  87. package/src/rules/no-debug-code-in-production/index.d.ts +0 -8
  88. package/src/rules/no-debug-code-in-production/index.js +0 -51
  89. package/src/rules/no-disabled-certificate-validation/index.d.ts +0 -6
  90. package/src/rules/no-disabled-certificate-validation/index.js +0 -61
  91. package/src/rules/no-dynamic-dependency-loading/index.d.ts +0 -8
  92. package/src/rules/no-dynamic-dependency-loading/index.js +0 -51
  93. package/src/rules/no-exposed-debug-endpoints/index.d.ts +0 -6
  94. package/src/rules/no-exposed-debug-endpoints/index.js +0 -62
  95. package/src/rules/no-exposed-sensitive-data/index.d.ts +0 -11
  96. package/src/rules/no-exposed-sensitive-data/index.js +0 -340
  97. package/src/rules/no-http-urls/index.d.ts +0 -12
  98. package/src/rules/no-http-urls/index.js +0 -114
  99. package/src/rules/no-insecure-redirects/index.d.ts +0 -7
  100. package/src/rules/no-insecure-redirects/index.js +0 -216
  101. package/src/rules/no-insecure-websocket/index.d.ts +0 -6
  102. package/src/rules/no-insecure-websocket/index.js +0 -61
  103. package/src/rules/no-missing-cors-check/index.d.ts +0 -9
  104. package/src/rules/no-missing-cors-check/index.js +0 -399
  105. package/src/rules/no-missing-csrf-protection/index.d.ts +0 -11
  106. package/src/rules/no-missing-csrf-protection/index.js +0 -180
  107. package/src/rules/no-missing-security-headers/index.d.ts +0 -7
  108. package/src/rules/no-missing-security-headers/index.js +0 -218
  109. package/src/rules/no-password-in-url/index.d.ts +0 -8
  110. package/src/rules/no-password-in-url/index.js +0 -54
  111. package/src/rules/no-permissive-cors/index.d.ts +0 -8
  112. package/src/rules/no-permissive-cors/index.js +0 -65
  113. package/src/rules/no-sensitive-data-in-analytics/index.d.ts +0 -8
  114. package/src/rules/no-sensitive-data-in-analytics/index.js +0 -62
  115. package/src/rules/no-sensitive-data-in-cache/index.d.ts +0 -8
  116. package/src/rules/no-sensitive-data-in-cache/index.js +0 -52
  117. package/src/rules/no-toctou-vulnerability/index.d.ts +0 -7
  118. package/src/rules/no-toctou-vulnerability/index.js +0 -208
  119. package/src/rules/no-tracking-without-consent/index.d.ts +0 -6
  120. package/src/rules/no-tracking-without-consent/index.js +0 -67
  121. package/src/rules/no-unencrypted-transmission/index.d.ts +0 -11
  122. package/src/rules/no-unencrypted-transmission/index.js +0 -236
  123. package/src/rules/no-unescaped-url-parameter/index.d.ts +0 -9
  124. package/src/rules/no-unescaped-url-parameter/index.js +0 -355
  125. package/src/rules/no-unsafe-dynamic-require/index.d.ts +0 -5
  126. package/src/rules/no-unsafe-dynamic-require/index.js +0 -106
  127. package/src/rules/no-unvalidated-deeplinks/index.d.ts +0 -6
  128. package/src/rules/no-unvalidated-deeplinks/index.js +0 -62
  129. package/src/rules/no-unvalidated-user-input/index.d.ts +0 -9
  130. package/src/rules/no-unvalidated-user-input/index.js +0 -420
  131. package/src/rules/no-verbose-error-messages/index.d.ts +0 -8
  132. package/src/rules/no-verbose-error-messages/index.js +0 -68
  133. package/src/rules/no-zip-slip/index.d.ts +0 -9
  134. package/src/rules/no-zip-slip/index.js +0 -445
  135. package/src/rules/require-code-minification/index.d.ts +0 -8
  136. package/src/rules/require-code-minification/index.js +0 -47
  137. package/src/rules/require-csp-headers/index.d.ts +0 -6
  138. package/src/rules/require-csp-headers/index.js +0 -64
  139. package/src/rules/require-data-minimization/index.d.ts +0 -8
  140. package/src/rules/require-data-minimization/index.js +0 -53
  141. package/src/rules/require-dependency-integrity/index.d.ts +0 -6
  142. package/src/rules/require-dependency-integrity/index.js +0 -64
  143. package/src/rules/require-https-only/index.d.ts +0 -8
  144. package/src/rules/require-https-only/index.js +0 -62
  145. package/src/rules/require-mime-type-validation/index.d.ts +0 -6
  146. package/src/rules/require-mime-type-validation/index.js +0 -66
  147. package/src/rules/require-network-timeout/index.d.ts +0 -8
  148. package/src/rules/require-network-timeout/index.js +0 -50
  149. package/src/rules/require-package-lock/index.d.ts +0 -8
  150. package/src/rules/require-package-lock/index.js +0 -63
  151. package/src/rules/require-secure-credential-storage/index.d.ts +0 -8
  152. package/src/rules/require-secure-credential-storage/index.js +0 -50
  153. package/src/rules/require-secure-deletion/index.d.ts +0 -8
  154. package/src/rules/require-secure-deletion/index.js +0 -44
  155. package/src/rules/require-storage-encryption/index.d.ts +0 -8
  156. package/src/rules/require-storage-encryption/index.js +0 -50
  157. package/src/rules/require-url-validation/index.d.ts +0 -6
  158. package/src/rules/require-url-validation/index.js +0 -72
@@ -1,195 +0,0 @@
1
- "use strict";
2
- /**
3
- * @fileoverview Prevent file access from user input
4
- *
5
- * False Positive Reduction:
6
- * This rule detects safe patterns including:
7
- * - path.basename() sanitization
8
- * - path.join() with validated base directories
9
- * - startsWith() validation guards
10
- * - Early-return throw patterns
11
- */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.noArbitraryFileAccess = void 0;
14
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
15
- exports.noArbitraryFileAccess = (0, eslint_devkit_1.createRule)({
16
- name: 'no-arbitrary-file-access',
17
- meta: {
18
- type: 'problem',
19
- docs: {
20
- description: 'Prevent file access from user input',
21
- },
22
- messages: {
23
- violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
24
- icon: eslint_devkit_1.MessageIcons.SECURITY,
25
- issueName: 'Arbitrary File Access',
26
- cwe: 'CWE-22',
27
- description: 'File path from user input - path traversal vulnerability',
28
- severity: 'HIGH',
29
- fix: 'Validate and sanitize file paths, use allowlists',
30
- documentationLink: 'https://cwe.mitre.org/data/definitions/22.html',
31
- })
32
- },
33
- schema: [],
34
- },
35
- defaultOptions: [],
36
- create(context) {
37
- const sourceCode = context.sourceCode;
38
- function report(node) {
39
- context.report({ node, messageId: 'violationDetected' });
40
- }
41
- const fsReadMethods = ['readFile', 'readFileSync', 'readdir', 'readdirSync', 'stat', 'statSync'];
42
- const fsWriteMethods = ['writeFile', 'writeFileSync', 'appendFile', 'appendFileSync'];
43
- const userInputSources = ['req', 'request', 'params', 'query', 'body'];
44
- // Track variables that have been sanitized with path.basename()
45
- const sanitizedVariables = new Set();
46
- // Track variables that have been validated with startsWith() guards
47
- const validatedVariables = new Set();
48
- /**
49
- * Check if a variable is assigned from path.basename() or path.join() with basename
50
- */
51
- function checkVariableDeclaration(node) {
52
- if (node.id.type !== 'Identifier' || !node.init) {
53
- return;
54
- }
55
- const varName = node.id.name;
56
- const init = node.init;
57
- // Check for path.basename() assignment
58
- if (init.type === 'CallExpression' &&
59
- init.callee.type === 'MemberExpression' &&
60
- init.callee.object.type === 'Identifier' &&
61
- init.callee.object.name === 'path' &&
62
- init.callee.property.type === 'Identifier' &&
63
- init.callee.property.name === 'basename') {
64
- sanitizedVariables.add(varName);
65
- }
66
- // Check for path.join() with a sanitized variable or literal base
67
- if (init.type === 'CallExpression' &&
68
- init.callee.type === 'MemberExpression' &&
69
- init.callee.object.type === 'Identifier' &&
70
- init.callee.object.name === 'path' &&
71
- init.callee.property.type === 'Identifier' &&
72
- init.callee.property.name === 'join') {
73
- // Check if any argument is a sanitized variable
74
- const hasSanitizedArg = init.arguments.some((arg) => arg.type === 'Identifier' && sanitizedVariables.has(arg.name));
75
- // Check if first arg is a safe base (literal or known safe variable)
76
- const firstArg = init.arguments[0];
77
- const hasSafeBase = firstArg && (firstArg.type === 'Literal' ||
78
- (firstArg.type === 'Identifier' && /^(SAFE|BASE|ROOT|UPLOAD|PUBLIC)/i.test(firstArg.name)));
79
- if (hasSanitizedArg && hasSafeBase) {
80
- sanitizedVariables.add(varName);
81
- }
82
- }
83
- }
84
- /**
85
- * Check if there's a startsWith() guard validation for this variable
86
- * Looks for patterns like:
87
- * if (!path.startsWith(baseDir)) { throw ... }
88
- * if (!path.startsWith(baseDir)) { return ... }
89
- */
90
- function hasStartsWithGuard(node, varName) {
91
- // Already validated
92
- if (validatedVariables.has(varName)) {
93
- return true;
94
- }
95
- // Walk up to find the containing block or function
96
- let current = node.parent;
97
- while (current) {
98
- // If we've reached a function body or block, search its statements
99
- if (current.type === eslint_devkit_1.AST_NODE_TYPES.BlockStatement) {
100
- const statements = current.body;
101
- // Look for IF statements in this block that validate our variable
102
- for (const stmt of statements) {
103
- if (stmt.type === eslint_devkit_1.AST_NODE_TYPES.IfStatement) {
104
- const testText = sourceCode.getText(stmt.test).toLowerCase();
105
- // Check for startsWith() validation pattern with our variable
106
- if (testText.includes('startswith') && testText.includes(varName.toLowerCase())) {
107
- // Check if this is a guard clause (negated condition with throw/return)
108
- const consequent = stmt.consequent;
109
- // Handle block statement: if (...) { throw/return; }
110
- if (consequent.type === eslint_devkit_1.AST_NODE_TYPES.BlockStatement && consequent.body.length > 0) {
111
- const firstStmt = consequent.body[0];
112
- if (firstStmt.type === eslint_devkit_1.AST_NODE_TYPES.ThrowStatement || firstStmt.type === eslint_devkit_1.AST_NODE_TYPES.ReturnStatement) {
113
- validatedVariables.add(varName);
114
- return true;
115
- }
116
- }
117
- // Handle direct statement: if (...) throw/return;
118
- if (consequent.type === eslint_devkit_1.AST_NODE_TYPES.ThrowStatement || consequent.type === eslint_devkit_1.AST_NODE_TYPES.ReturnStatement) {
119
- validatedVariables.add(varName);
120
- return true;
121
- }
122
- }
123
- }
124
- }
125
- }
126
- // Also check if current IS an if statement (when node is inside the consequent)
127
- if (current.type === eslint_devkit_1.AST_NODE_TYPES.IfStatement) {
128
- const testText = sourceCode.getText(current.test).toLowerCase();
129
- if (testText.includes('startswith') && testText.includes(varName.toLowerCase())) {
130
- validatedVariables.add(varName);
131
- return true;
132
- }
133
- }
134
- current = current.parent;
135
- }
136
- return false;
137
- }
138
- /**
139
- * Check if a variable comes from a sanitized/validated source
140
- */
141
- function isVariableSafe(varName, node) {
142
- // Already tracked as sanitized
143
- if (sanitizedVariables.has(varName)) {
144
- return true;
145
- }
146
- // Has startsWith guard validation
147
- if (hasStartsWithGuard(node, varName)) {
148
- return true;
149
- }
150
- // Check naming conventions that suggest safety
151
- if (/^(safe|sanitized|validated|clean)/i.test(varName)) {
152
- return true;
153
- }
154
- return false;
155
- }
156
- return {
157
- // Track variable declarations for sanitization patterns
158
- VariableDeclarator(node) {
159
- checkVariableDeclaration(node);
160
- },
161
- CallExpression(node) {
162
- // Detect fs.* with user input
163
- if (node.callee.type === 'MemberExpression' &&
164
- node.callee.object.type === 'Identifier' &&
165
- node.callee.object.name === 'fs' &&
166
- node.callee.property.type === 'Identifier' &&
167
- [...fsReadMethods, ...fsWriteMethods].includes(node.callee.property.name)) {
168
- const pathArg = node.arguments[0];
169
- // Skip if path is a literal (safe)
170
- if (pathArg && pathArg.type === 'Literal') {
171
- return;
172
- }
173
- // Check if path is a variable
174
- if (pathArg && pathArg.type === 'Identifier') {
175
- const varName = pathArg.name;
176
- // Skip if variable is sanitized or validated
177
- if (isVariableSafe(varName, node)) {
178
- return;
179
- }
180
- report(node);
181
- return;
182
- }
183
- // Flag if path is from a member expression (user input sources)
184
- if (pathArg?.type === 'MemberExpression' &&
185
- pathArg.object.type === 'Identifier') {
186
- const objName = pathArg.object.name.toLowerCase();
187
- if (userInputSources.includes(objName)) {
188
- report(node);
189
- }
190
- }
191
- }
192
- },
193
- };
194
- },
195
- });
@@ -1,29 +0,0 @@
1
- /**
2
- * ESLint Rule: no-buffer-overread
3
- * Detects buffer access beyond bounds (CWE-126)
4
- *
5
- * Buffer overread occurs when reading from buffers beyond their allocated
6
- * length, potentially leading to information disclosure, crashes, or
7
- * other security issues.
8
- *
9
- * False Positive Reduction:
10
- * This rule uses security utilities to reduce false positives by detecting:
11
- * - Safe buffer access patterns
12
- * - Bounds checking operations
13
- * - JSDoc annotations (@safe, @validated)
14
- * - Input validation functions
15
- */
16
- import type { SecurityRuleOptions } from '@interlace/eslint-devkit';
17
- export interface Options extends SecurityRuleOptions {
18
- /** Buffer methods to check for bounds safety */
19
- bufferMethods?: string[];
20
- /** Functions that validate buffer indices */
21
- boundsCheckFunctions?: string[];
22
- /** Buffer types to monitor */
23
- bufferTypes?: string[];
24
- /** Additional function names to consider as buffer index validators */
25
- trustedSanitizers?: string[];
26
- /** Additional JSDoc annotations to consider as safe markers */
27
- strictMode?: boolean;
28
- }
29
- export declare const noBufferOverread: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;