eslint-plugin-secure-coding 3.0.1 → 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 (130) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +60 -226
  3. package/package.json +6 -5
  4. package/src/index.d.ts +2 -2
  5. package/src/index.js +29 -263
  6. package/src/rules/detect-non-literal-regexp/index.d.ts +3 -1
  7. package/src/rules/detect-object-injection/index.d.ts +3 -1
  8. package/src/rules/detect-weak-password-validation/index.d.ts +3 -1
  9. package/src/rules/no-directive-injection/index.d.ts +3 -1
  10. package/src/rules/no-electron-security-issues/index.d.ts +3 -1
  11. package/src/rules/no-format-string-injection/index.d.ts +3 -1
  12. package/src/rules/no-graphql-injection/index.d.ts +3 -1
  13. package/src/rules/no-hardcoded-credentials/index.d.ts +3 -1
  14. package/src/rules/no-hardcoded-session-tokens/index.d.ts +3 -1
  15. package/src/rules/no-improper-sanitization/index.d.ts +3 -1
  16. package/src/rules/no-improper-type-validation/index.d.ts +3 -1
  17. package/src/rules/no-insecure-comparison/index.d.ts +3 -1
  18. package/src/rules/no-ldap-injection/index.d.ts +3 -1
  19. package/src/rules/no-missing-authentication/index.d.ts +3 -1
  20. package/src/rules/no-missing-authentication/index.js +0 -1
  21. package/src/rules/no-pii-in-logs/index.d.ts +3 -1
  22. package/src/rules/no-privilege-escalation/index.d.ts +3 -1
  23. package/src/rules/no-redos-vulnerable-regex/index.d.ts +3 -1
  24. package/src/rules/no-sensitive-data-exposure/index.d.ts +3 -1
  25. package/src/rules/no-unchecked-loop-condition/index.d.ts +3 -1
  26. package/src/rules/no-unlimited-resource-allocation/index.d.ts +3 -1
  27. package/src/rules/no-unsafe-deserialization/index.d.ts +3 -1
  28. package/src/rules/no-unsafe-regex-construction/index.d.ts +3 -1
  29. package/src/rules/no-weak-password-recovery/index.d.ts +3 -1
  30. package/src/rules/no-xpath-injection/index.d.ts +3 -1
  31. package/src/rules/no-xxe-injection/index.d.ts +3 -1
  32. package/src/rules/require-backend-authorization/index.d.ts +3 -1
  33. package/src/rules/require-secure-defaults/index.d.ts +3 -1
  34. package/src/types/index.d.ts +5 -52
  35. package/src/rules/detect-child-process/index.d.ts +0 -28
  36. package/src/rules/detect-child-process/index.js +0 -534
  37. package/src/rules/detect-eval-with-expression/index.d.ts +0 -26
  38. package/src/rules/detect-eval-with-expression/index.js +0 -397
  39. package/src/rules/detect-mixed-content/index.d.ts +0 -10
  40. package/src/rules/detect-mixed-content/index.js +0 -45
  41. package/src/rules/detect-non-literal-fs-filename/index.d.ts +0 -24
  42. package/src/rules/detect-non-literal-fs-filename/index.js +0 -459
  43. package/src/rules/detect-suspicious-dependencies/index.d.ts +0 -10
  44. package/src/rules/detect-suspicious-dependencies/index.js +0 -76
  45. package/src/rules/no-allow-arbitrary-loads/index.d.ts +0 -10
  46. package/src/rules/no-allow-arbitrary-loads/index.js +0 -48
  47. package/src/rules/no-arbitrary-file-access/index.d.ts +0 -10
  48. package/src/rules/no-arbitrary-file-access/index.js +0 -200
  49. package/src/rules/no-buffer-overread/index.d.ts +0 -37
  50. package/src/rules/no-buffer-overread/index.js +0 -611
  51. package/src/rules/no-clickjacking/index.d.ts +0 -34
  52. package/src/rules/no-clickjacking/index.js +0 -401
  53. package/src/rules/no-client-side-auth-logic/index.d.ts +0 -10
  54. package/src/rules/no-client-side-auth-logic/index.js +0 -74
  55. package/src/rules/no-credentials-in-query-params/index.d.ts +0 -10
  56. package/src/rules/no-credentials-in-query-params/index.js +0 -62
  57. package/src/rules/no-data-in-temp-storage/index.d.ts +0 -10
  58. package/src/rules/no-data-in-temp-storage/index.js +0 -69
  59. package/src/rules/no-debug-code-in-production/index.d.ts +0 -10
  60. package/src/rules/no-debug-code-in-production/index.js +0 -54
  61. package/src/rules/no-disabled-certificate-validation/index.d.ts +0 -10
  62. package/src/rules/no-disabled-certificate-validation/index.js +0 -66
  63. package/src/rules/no-dynamic-dependency-loading/index.d.ts +0 -10
  64. package/src/rules/no-dynamic-dependency-loading/index.js +0 -54
  65. package/src/rules/no-exposed-debug-endpoints/index.d.ts +0 -10
  66. package/src/rules/no-exposed-debug-endpoints/index.js +0 -67
  67. package/src/rules/no-exposed-sensitive-data/index.d.ts +0 -28
  68. package/src/rules/no-exposed-sensitive-data/index.js +0 -345
  69. package/src/rules/no-http-urls/index.d.ts +0 -15
  70. package/src/rules/no-http-urls/index.js +0 -119
  71. package/src/rules/no-insecure-redirects/index.d.ts +0 -24
  72. package/src/rules/no-insecure-redirects/index.js +0 -221
  73. package/src/rules/no-insecure-websocket/index.d.ts +0 -10
  74. package/src/rules/no-insecure-websocket/index.js +0 -66
  75. package/src/rules/no-missing-cors-check/index.d.ts +0 -26
  76. package/src/rules/no-missing-cors-check/index.js +0 -404
  77. package/src/rules/no-missing-csrf-protection/index.d.ts +0 -28
  78. package/src/rules/no-missing-csrf-protection/index.js +0 -185
  79. package/src/rules/no-missing-security-headers/index.d.ts +0 -24
  80. package/src/rules/no-missing-security-headers/index.js +0 -223
  81. package/src/rules/no-password-in-url/index.d.ts +0 -10
  82. package/src/rules/no-password-in-url/index.js +0 -55
  83. package/src/rules/no-permissive-cors/index.d.ts +0 -10
  84. package/src/rules/no-permissive-cors/index.js +0 -74
  85. package/src/rules/no-sensitive-data-in-analytics/index.d.ts +0 -10
  86. package/src/rules/no-sensitive-data-in-analytics/index.js +0 -66
  87. package/src/rules/no-sensitive-data-in-cache/index.d.ts +0 -10
  88. package/src/rules/no-sensitive-data-in-cache/index.js +0 -53
  89. package/src/rules/no-toctou-vulnerability/index.d.ts +0 -24
  90. package/src/rules/no-toctou-vulnerability/index.js +0 -213
  91. package/src/rules/no-tracking-without-consent/index.d.ts +0 -10
  92. package/src/rules/no-tracking-without-consent/index.js +0 -72
  93. package/src/rules/no-unencrypted-transmission/index.d.ts +0 -28
  94. package/src/rules/no-unencrypted-transmission/index.js +0 -241
  95. package/src/rules/no-unescaped-url-parameter/index.d.ts +0 -26
  96. package/src/rules/no-unescaped-url-parameter/index.js +0 -360
  97. package/src/rules/no-unsafe-dynamic-require/index.d.ts +0 -17
  98. package/src/rules/no-unsafe-dynamic-require/index.js +0 -111
  99. package/src/rules/no-unvalidated-deeplinks/index.d.ts +0 -10
  100. package/src/rules/no-unvalidated-deeplinks/index.js +0 -67
  101. package/src/rules/no-unvalidated-user-input/index.d.ts +0 -26
  102. package/src/rules/no-unvalidated-user-input/index.js +0 -425
  103. package/src/rules/no-verbose-error-messages/index.d.ts +0 -10
  104. package/src/rules/no-verbose-error-messages/index.js +0 -73
  105. package/src/rules/no-zip-slip/index.d.ts +0 -33
  106. package/src/rules/no-zip-slip/index.js +0 -450
  107. package/src/rules/require-code-minification/index.d.ts +0 -10
  108. package/src/rules/require-code-minification/index.js +0 -48
  109. package/src/rules/require-csp-headers/index.d.ts +0 -10
  110. package/src/rules/require-csp-headers/index.js +0 -69
  111. package/src/rules/require-data-minimization/index.d.ts +0 -10
  112. package/src/rules/require-data-minimization/index.js +0 -55
  113. package/src/rules/require-dependency-integrity/index.d.ts +0 -10
  114. package/src/rules/require-dependency-integrity/index.js +0 -69
  115. package/src/rules/require-https-only/index.d.ts +0 -10
  116. package/src/rules/require-https-only/index.js +0 -67
  117. package/src/rules/require-mime-type-validation/index.d.ts +0 -10
  118. package/src/rules/require-mime-type-validation/index.js +0 -71
  119. package/src/rules/require-network-timeout/index.d.ts +0 -10
  120. package/src/rules/require-network-timeout/index.js +0 -57
  121. package/src/rules/require-package-lock/index.d.ts +0 -10
  122. package/src/rules/require-package-lock/index.js +0 -64
  123. package/src/rules/require-secure-credential-storage/index.d.ts +0 -10
  124. package/src/rules/require-secure-credential-storage/index.js +0 -53
  125. package/src/rules/require-secure-deletion/index.d.ts +0 -10
  126. package/src/rules/require-secure-deletion/index.js +0 -45
  127. package/src/rules/require-storage-encryption/index.d.ts +0 -10
  128. package/src/rules/require-storage-encryption/index.js +0 -53
  129. package/src/rules/require-url-validation/index.d.ts +0 -10
  130. package/src/rules/require-url-validation/index.js +0 -77
@@ -1,119 +0,0 @@
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.noHttpUrls = void 0;
9
- /**
10
- * @fileoverview Disallow hardcoded HTTP URLs
11
- * @see https://owasp.org/www-project-mobile-top-10/
12
- * @see https://cwe.mitre.org/data/definitions/319.html
13
- */
14
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
15
- exports.noHttpUrls = (0, eslint_devkit_1.createRule)({
16
- name: 'no-http-urls',
17
- meta: {
18
- type: 'problem',
19
- docs: {
20
- description: 'Disallow hardcoded HTTP URLs (require HTTPS)',
21
- },
22
- messages: {
23
- insecureHttp: (0, eslint_devkit_1.formatLLMMessage)({
24
- icon: eslint_devkit_1.MessageIcons.SECURITY,
25
- issueName: 'Insecure HTTP URL',
26
- cwe: 'CWE-319',
27
- owasp: 'A02:2021',
28
- cvss: 7.5,
29
- description: 'Hardcoded HTTP URL detected: "{{url}}"',
30
- severity: 'HIGH',
31
- compliance: ['SOC2', 'PCI-DSS', 'HIPAA'],
32
- fix: 'Use HTTPS instead: const url = "https://..."',
33
- documentationLink: 'https://cwe.mitre.org/data/definitions/319.html',
34
- }),
35
- insecureHttpWithException: (0, eslint_devkit_1.formatLLMMessage)({
36
- icon: eslint_devkit_1.MessageIcons.WARNING,
37
- issueName: 'Insecure HTTP URL',
38
- cwe: 'CWE-319',
39
- owasp: 'A02:2021',
40
- cvss: 5.3,
41
- description: 'HTTP URL detected: "{{url}}"',
42
- severity: 'MEDIUM',
43
- fix: 'Use HTTPS or add to allowedHosts config',
44
- documentationLink: 'https://cwe.mitre.org/data/definitions/319.html',
45
- }),
46
- },
47
- schema: [
48
- {
49
- type: 'object',
50
- properties: {
51
- allowedHosts: {
52
- type: 'array',
53
- items: { type: 'string' },
54
- description: 'List of hostnames allowed to use HTTP (e.g., localhost, 127.0.0.1)',
55
- },
56
- allowedPorts: {
57
- type: 'array',
58
- items: { type: 'number' },
59
- description: 'List of ports allowed for HTTP (e.g., 3000, 8080 for development)',
60
- },
61
- },
62
- additionalProperties: false,
63
- },
64
- ],
65
- },
66
- defaultOptions: [
67
- {
68
- allowedHosts: ['localhost', '127.0.0.1'],
69
- allowedPorts: [],
70
- },
71
- ],
72
- create(context) {
73
- const [options = {}] = context.options;
74
- const allowedHosts = options.allowedHosts ?? ['localhost', '127.0.0.1'];
75
- const allowedPorts = options.allowedPorts ?? [];
76
- function isAllowedException(url) {
77
- try {
78
- const parsedUrl = new URL(url);
79
- // Check if host is in allowed list
80
- if (allowedHosts.includes(parsedUrl.hostname)) {
81
- return true;
82
- }
83
- // Check if port is in allowed list
84
- if (parsedUrl.port && allowedPorts.includes(parseInt(parsedUrl.port, 10))) {
85
- return true;
86
- }
87
- return false;
88
- }
89
- catch {
90
- // If URL parsing fails, treat as pattern match
91
- return allowedHosts.some(host => url.includes(host));
92
- }
93
- }
94
- function checkStringValue(node, value) {
95
- const httpPattern = /^http:\/\//i;
96
- if (httpPattern.test(value) && !isAllowedException(value)) {
97
- context.report({
98
- node,
99
- messageId: allowedHosts.length > 0 || allowedPorts.length > 0
100
- ? 'insecureHttpWithException'
101
- : 'insecureHttp',
102
- data: { url: value },
103
- });
104
- }
105
- }
106
- return {
107
- Literal(node) {
108
- if (typeof node.value === 'string') {
109
- checkStringValue(node, node.value);
110
- }
111
- },
112
- TemplateElement(node) {
113
- if (node.value.cooked) {
114
- checkStringValue(node, node.value.cooked);
115
- }
116
- },
117
- };
118
- },
119
- });
@@ -1,24 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Ofri Peretz
3
- * Licensed under the MIT License. Use of this source code is governed by the
4
- * MIT license that can be found in the LICENSE file.
5
- */
6
- /**
7
- * ESLint Rule: no-insecure-redirects
8
- * Detects open redirect vulnerabilities
9
- * CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
10
- *
11
- * @see https://cwe.mitre.org/data/definitions/601.html
12
- * @see https://owasp.org/www-community/vulnerabilities/Unvalidated_Redirects_and_Forwards
13
- */
14
- import type { TSESLint } from '@interlace/eslint-devkit';
15
- type MessageIds = 'insecureRedirect' | 'whitelistDomains' | 'validateRedirect' | 'useRelativeUrl';
16
- export interface Options {
17
- /** Ignore in test files. Default: true */
18
- ignoreInTests?: boolean;
19
- /** Allowed redirect domains. Default: [] */
20
- allowedDomains?: string[];
21
- }
22
- type RuleOptions = [Options?];
23
- export declare const noInsecureRedirects: TSESLint.RuleModule<MessageIds, RuleOptions, unknown, TSESLint.RuleListener>;
24
- export {};
@@ -1,221 +0,0 @@
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.noInsecureRedirects = void 0;
9
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
11
- /**
12
- * Check if redirect URL is validated
13
- */
14
- function isRedirectValidated(node, sourceCode) {
15
- const callText = sourceCode.getText(node);
16
- // Check if URL is from user input (req.query, req.body, req.params)
17
- const userInputPattern = /\b(req\.(query|body|params)|window\.location|document\.location)\b/;
18
- if (!userInputPattern.test(callText)) {
19
- // Not from user input, assume safe
20
- return true;
21
- }
22
- // Look for validation patterns in the surrounding code
23
- // This is a simplified static analysis - in practice, would need data flow analysis
24
- const program = sourceCode.ast;
25
- const nodeStart = node.loc?.start;
26
- const nodeEnd = node.loc?.end;
27
- /* c8 ignore start -- Guard clause: loc is always present in RuleTester */
28
- if (!nodeStart || !nodeEnd || !program) {
29
- return false;
30
- }
31
- /* c8 ignore stop */
32
- // Check for validation function calls before this redirect
33
- const validationPatterns = [
34
- /\b(validateUrl|validateRedirect|isValidUrl|isSafeUrl)\s*\(/,
35
- /\b(whitelist|allowedDomains|permittedUrls)\s*\./,
36
- /\b(url\.hostname|url\.host)\s*===/,
37
- /\ballowedDomains\.includes\s*\(/,
38
- /\bstartsWith\s*\(\s*['"]/,
39
- /\bendsWith\s*\(\s*['"]/,
40
- /\bindexOf\s*\(\s*['"]/,
41
- /\bmatch\s*\(\s*\//,
42
- ];
43
- // Look for validation in the same function scope
44
- let current = node;
45
- let depth = 0;
46
- const maxDepth = 20;
47
- while (current && depth < maxDepth) {
48
- // Check siblings before this node
49
- const parent = current.parent;
50
- if (!parent)
51
- break;
52
- if (parent.type === 'BlockStatement') {
53
- const body = parent.body;
54
- const currentIndex = body.indexOf(current);
55
- // Check previous statements in the same block
56
- for (let i = currentIndex - 1; i >= 0 && i >= currentIndex - 5; i--) {
57
- const stmt = body[i];
58
- const stmtText = sourceCode.getText(stmt);
59
- if (validationPatterns.some(pattern => pattern.test(stmtText))) {
60
- return true; // Found validation
61
- }
62
- }
63
- }
64
- current = parent;
65
- depth++;
66
- }
67
- // No validation found
68
- return false;
69
- }
70
- exports.noInsecureRedirects = (0, eslint_devkit_2.createRule)({
71
- name: 'no-insecure-redirects',
72
- meta: {
73
- type: 'problem',
74
- docs: {
75
- description: 'Detects open redirect vulnerabilities',
76
- },
77
- hasSuggestions: true,
78
- messages: {
79
- insecureRedirect: (0, eslint_devkit_1.formatLLMMessage)({
80
- icon: eslint_devkit_1.MessageIcons.SECURITY,
81
- issueName: 'Open redirect',
82
- cwe: 'CWE-601',
83
- description: 'Unvalidated redirect detected - user-controlled URL',
84
- severity: 'HIGH',
85
- fix: 'Whitelist allowed domains or validate redirect target',
86
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Unvalidated_Redirects_and_Forwards',
87
- }),
88
- whitelistDomains: (0, eslint_devkit_1.formatLLMMessage)({
89
- icon: eslint_devkit_1.MessageIcons.INFO,
90
- issueName: 'Whitelist Domains',
91
- description: 'Whitelist allowed redirect domains',
92
- severity: 'LOW',
93
- fix: 'if (allowedDomains.includes(url.hostname)) redirect(url)',
94
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Unvalidated_Redirects_and_Forwards',
95
- }),
96
- validateRedirect: (0, eslint_devkit_1.formatLLMMessage)({
97
- icon: eslint_devkit_1.MessageIcons.INFO,
98
- issueName: 'Validate Redirect',
99
- description: 'Validate redirect URL before use',
100
- severity: 'LOW',
101
- fix: 'validateRedirectUrl(userInput) before redirect',
102
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Unvalidated_Redirects_and_Forwards',
103
- }),
104
- useRelativeUrl: (0, eslint_devkit_1.formatLLMMessage)({
105
- icon: eslint_devkit_1.MessageIcons.INFO,
106
- issueName: 'Use Relative URL',
107
- description: 'Use relative URLs for internal redirects',
108
- severity: 'LOW',
109
- fix: 'redirect("/internal/path") instead of absolute URLs',
110
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Unvalidated_Redirects_and_Forwards',
111
- }),
112
- },
113
- schema: [
114
- {
115
- type: 'object',
116
- properties: {
117
- ignoreInTests: {
118
- type: 'boolean',
119
- default: true,
120
- },
121
- allowedDomains: {
122
- type: 'array',
123
- items: { type: 'string' },
124
- default: [],
125
- },
126
- },
127
- additionalProperties: false,
128
- },
129
- ],
130
- },
131
- defaultOptions: [
132
- {
133
- ignoreInTests: true,
134
- allowedDomains: [],
135
- },
136
- ],
137
- create(context, [options = {}]) {
138
- const { ignoreInTests = true } = options || {};
139
- const filename = context.getFilename();
140
- const isTestFile = ignoreInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
141
- if (isTestFile) {
142
- return {};
143
- }
144
- const sourceCode = context.sourceCode || context.sourceCode;
145
- /**
146
- * Check redirect calls and assignments
147
- */
148
- function checkCallExpression(node) {
149
- // Check for res.redirect, window.location, etc.
150
- if (node.callee.type === 'MemberExpression' &&
151
- node.callee.property.type === 'Identifier') {
152
- const methodName = node.callee.property.name;
153
- if (['redirect', 'replace', 'assign'].includes(methodName)) {
154
- // Check if redirect URL is validated
155
- if (!isRedirectValidated(node, sourceCode)) {
156
- context.report({
157
- node,
158
- messageId: 'insecureRedirect',
159
- suggest: [
160
- {
161
- messageId: 'whitelistDomains',
162
- fix: () => null,
163
- },
164
- {
165
- messageId: 'validateRedirect',
166
- fix: () => null,
167
- },
168
- {
169
- messageId: 'useRelativeUrl',
170
- fix: () => null,
171
- },
172
- ],
173
- });
174
- }
175
- }
176
- }
177
- }
178
- /**
179
- * Check assignment expressions like window.location.href = ...
180
- */
181
- function checkAssignmentExpression(node) {
182
- // Check for window.location.href assignments
183
- if (node.left.type === 'MemberExpression' &&
184
- node.left.object.type === 'MemberExpression' &&
185
- node.left.object.object.type === 'Identifier' &&
186
- node.left.object.object.name === 'window' &&
187
- node.left.object.property.type === 'Identifier' &&
188
- node.left.object.property.name === 'location' &&
189
- node.left.property.type === 'Identifier' &&
190
- ['href', 'replace', 'assign'].includes(node.left.property.name)) {
191
- // Check if assignment value comes from user input
192
- const rightText = sourceCode.getText(node.right);
193
- const userInputPattern = /\b(req\.(query|body|params)|window\.location|document\.location)\b/;
194
- if (userInputPattern.test(rightText)) {
195
- context.report({
196
- node,
197
- messageId: 'insecureRedirect',
198
- suggest: [
199
- {
200
- messageId: 'whitelistDomains',
201
- fix: () => null,
202
- },
203
- {
204
- messageId: 'validateRedirect',
205
- fix: () => null,
206
- },
207
- {
208
- messageId: 'useRelativeUrl',
209
- fix: () => null,
210
- },
211
- ],
212
- });
213
- }
214
- }
215
- }
216
- return {
217
- CallExpression: checkCallExpression,
218
- AssignmentExpression: checkAssignmentExpression,
219
- };
220
- },
221
- });
@@ -1,10 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Ofri Peretz
3
- * Licensed under the MIT License. Use of this source code is governed by the
4
- * MIT license that can be found in the LICENSE file.
5
- */
6
- export interface Options {
7
- }
8
- type RuleOptions = [Options?];
9
- export declare const noInsecureWebsocket: import("@typescript-eslint/utils/ts-eslint").RuleModule<"violationDetected", RuleOptions, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
10
- export {};
@@ -1,66 +0,0 @@
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.noInsecureWebsocket = void 0;
9
- /**
10
- * @fileoverview Require secure WebSocket connections (wss://)
11
- */
12
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
13
- exports.noInsecureWebsocket = (0, eslint_devkit_1.createRule)({
14
- name: 'no-insecure-websocket',
15
- meta: {
16
- type: 'problem',
17
- docs: {
18
- description: 'Require secure WebSocket connections (wss://)',
19
- },
20
- messages: {
21
- violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
22
- icon: eslint_devkit_1.MessageIcons.SECURITY,
23
- issueName: 'Insecure WebSocket',
24
- cwe: 'CWE-319',
25
- description: 'Insecure WebSocket connection (ws://) - data transmitted in clear text',
26
- severity: 'HIGH',
27
- fix: 'Use wss:// instead of ws:// for secure WebSocket connections',
28
- documentationLink: 'https://cwe.mitre.org/data/definitions/319.html',
29
- })
30
- },
31
- schema: [],
32
- },
33
- defaultOptions: [],
34
- create(context) {
35
- function report(node) {
36
- context.report({ node, messageId: 'violationDetected' });
37
- }
38
- return {
39
- NewExpression(node) {
40
- // Check for new WebSocket('ws://...')
41
- if (node.callee.type === 'Identifier' && node.callee.name === 'WebSocket') {
42
- const urlArg = node.arguments[0];
43
- // Check literal string
44
- if (urlArg && urlArg.type === 'Literal' &&
45
- typeof urlArg.value === 'string' &&
46
- urlArg.value.startsWith('ws://')) {
47
- report(node);
48
- }
49
- // Check template literal
50
- if (urlArg && urlArg.type === 'TemplateLiteral') {
51
- const text = context.sourceCode.getText(urlArg);
52
- if (text.includes('ws://')) {
53
- report(node);
54
- }
55
- }
56
- }
57
- },
58
- Literal(node) {
59
- // Check for ws:// URLs in string literals
60
- if (typeof node.value === 'string' && node.value.startsWith('ws://')) {
61
- report(node);
62
- }
63
- },
64
- };
65
- },
66
- });
@@ -1,26 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Ofri Peretz
3
- * Licensed under the MIT License. Use of this source code is governed by the
4
- * MIT license that can be found in the LICENSE file.
5
- */
6
- /**
7
- * ESLint Rule: no-missing-cors-check
8
- * Detects missing CORS validation (wildcard CORS, missing origin check)
9
- * CWE-346: Origin Validation Error
10
- *
11
- * @see https://cwe.mitre.org/data/definitions/346.html
12
- * @see https://owasp.org/www-community/attacks/CORS_Misconfiguration
13
- */
14
- import type { TSESLint } from '@interlace/eslint-devkit';
15
- type MessageIds = 'missingCorsCheck' | 'useOriginValidation' | 'useCorsMiddleware';
16
- export interface Options {
17
- /** Allow missing CORS checks in test files. Default: false */
18
- allowInTests?: boolean;
19
- /** Trusted CORS libraries. Default: ['cors', '@koa/cors', 'express-cors'] */
20
- trustedLibraries?: string[];
21
- /** Additional safe patterns to ignore. Default: [] */
22
- ignorePatterns?: string[];
23
- }
24
- type RuleOptions = [Options?];
25
- export declare const noMissingCorsCheck: TSESLint.RuleModule<MessageIds, RuleOptions, unknown, TSESLint.RuleListener>;
26
- export {};