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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +1 -1
- package/README.md +90 -422
- package/package.json +6 -5
- package/src/index.d.ts +5 -14
- package/src/index.js +36 -265
- package/src/rules/detect-non-literal-regexp/index.d.ts +20 -1
- package/src/rules/detect-non-literal-regexp/index.js +5 -0
- package/src/rules/detect-object-injection/index.d.ts +25 -1
- package/src/rules/detect-object-injection/index.js +5 -0
- package/src/rules/detect-weak-password-validation/index.d.ts +8 -2
- package/src/rules/detect-weak-password-validation/index.js +6 -1
- package/src/rules/no-directive-injection/index.d.ts +27 -1
- package/src/rules/no-directive-injection/index.js +5 -0
- package/src/rules/no-electron-security-issues/index.d.ts +27 -1
- package/src/rules/no-electron-security-issues/index.js +5 -0
- package/src/rules/no-format-string-injection/index.d.ts +28 -1
- package/src/rules/no-format-string-injection/index.js +5 -0
- package/src/rules/no-graphql-injection/index.d.ts +29 -1
- package/src/rules/no-graphql-injection/index.js +5 -0
- package/src/rules/no-hardcoded-credentials/index.d.ts +19 -1
- package/src/rules/no-hardcoded-credentials/index.js +5 -0
- package/src/rules/no-hardcoded-session-tokens/index.d.ts +8 -2
- package/src/rules/no-hardcoded-session-tokens/index.js +6 -1
- package/src/rules/no-improper-sanitization/index.d.ts +27 -1
- package/src/rules/no-improper-sanitization/index.js +5 -0
- package/src/rules/no-improper-type-validation/index.d.ts +27 -1
- package/src/rules/no-improper-type-validation/index.js +5 -0
- package/src/rules/no-insecure-comparison/index.d.ts +20 -1
- package/src/rules/no-insecure-comparison/index.js +5 -0
- package/src/rules/no-ldap-injection/index.d.ts +30 -1
- package/src/rules/no-ldap-injection/index.js +5 -0
- package/src/rules/no-missing-authentication/index.d.ts +20 -1
- package/src/rules/no-missing-authentication/index.js +5 -1
- package/src/rules/no-pii-in-logs/index.d.ts +8 -4
- package/src/rules/no-pii-in-logs/index.js +15 -12
- package/src/rules/no-privilege-escalation/index.d.ts +20 -1
- package/src/rules/no-privilege-escalation/index.js +5 -0
- package/src/rules/no-redos-vulnerable-regex/index.d.ts +22 -1
- package/src/rules/no-redos-vulnerable-regex/index.js +5 -0
- package/src/rules/no-sensitive-data-exposure/index.d.ts +20 -1
- package/src/rules/no-sensitive-data-exposure/index.js +5 -0
- package/src/rules/no-unchecked-loop-condition/index.d.ts +27 -1
- package/src/rules/no-unchecked-loop-condition/index.js +5 -0
- package/src/rules/no-unlimited-resource-allocation/index.d.ts +27 -1
- package/src/rules/no-unlimited-resource-allocation/index.js +5 -0
- package/src/rules/no-unsafe-deserialization/index.d.ts +31 -1
- package/src/rules/no-unsafe-deserialization/index.js +5 -0
- package/src/rules/no-unsafe-regex-construction/index.d.ts +22 -1
- package/src/rules/no-unsafe-regex-construction/index.js +5 -0
- package/src/rules/no-weak-password-recovery/index.d.ts +27 -1
- package/src/rules/no-weak-password-recovery/index.js +5 -0
- package/src/rules/no-xpath-injection/index.d.ts +30 -1
- package/src/rules/no-xpath-injection/index.js +5 -0
- package/src/rules/no-xxe-injection/index.d.ts +30 -1
- package/src/rules/no-xxe-injection/index.js +5 -0
- package/src/rules/require-backend-authorization/index.d.ts +8 -2
- package/src/rules/require-backend-authorization/index.js +6 -1
- package/src/rules/require-secure-defaults/index.d.ts +8 -4
- package/src/rules/require-secure-defaults/index.js +7 -6
- package/src/types/index.d.ts +10 -52
- package/src/types/index.js +3 -12
- package/src/rules/detect-child-process/index.d.ts +0 -11
- package/src/rules/detect-child-process/index.js +0 -529
- package/src/rules/detect-eval-with-expression/index.d.ts +0 -9
- package/src/rules/detect-eval-with-expression/index.js +0 -392
- package/src/rules/detect-mixed-content/index.d.ts +0 -8
- package/src/rules/detect-mixed-content/index.js +0 -44
- package/src/rules/detect-non-literal-fs-filename/index.d.ts +0 -7
- package/src/rules/detect-non-literal-fs-filename/index.js +0 -454
- package/src/rules/detect-suspicious-dependencies/index.d.ts +0 -8
- package/src/rules/detect-suspicious-dependencies/index.js +0 -71
- package/src/rules/no-allow-arbitrary-loads/index.d.ts +0 -8
- package/src/rules/no-allow-arbitrary-loads/index.js +0 -47
- package/src/rules/no-arbitrary-file-access/index.d.ts +0 -13
- package/src/rules/no-arbitrary-file-access/index.js +0 -195
- package/src/rules/no-buffer-overread/index.d.ts +0 -29
- package/src/rules/no-buffer-overread/index.js +0 -606
- package/src/rules/no-clickjacking/index.d.ts +0 -10
- package/src/rules/no-clickjacking/index.js +0 -396
- package/src/rules/no-client-side-auth-logic/index.d.ts +0 -6
- package/src/rules/no-client-side-auth-logic/index.js +0 -69
- package/src/rules/no-credentials-in-query-params/index.d.ts +0 -8
- package/src/rules/no-credentials-in-query-params/index.js +0 -57
- package/src/rules/no-data-in-temp-storage/index.d.ts +0 -6
- package/src/rules/no-data-in-temp-storage/index.js +0 -64
- package/src/rules/no-debug-code-in-production/index.d.ts +0 -8
- package/src/rules/no-debug-code-in-production/index.js +0 -51
- package/src/rules/no-disabled-certificate-validation/index.d.ts +0 -6
- package/src/rules/no-disabled-certificate-validation/index.js +0 -61
- package/src/rules/no-dynamic-dependency-loading/index.d.ts +0 -8
- package/src/rules/no-dynamic-dependency-loading/index.js +0 -51
- package/src/rules/no-exposed-debug-endpoints/index.d.ts +0 -6
- package/src/rules/no-exposed-debug-endpoints/index.js +0 -62
- package/src/rules/no-exposed-sensitive-data/index.d.ts +0 -11
- package/src/rules/no-exposed-sensitive-data/index.js +0 -340
- package/src/rules/no-http-urls/index.d.ts +0 -12
- package/src/rules/no-http-urls/index.js +0 -114
- package/src/rules/no-insecure-redirects/index.d.ts +0 -7
- package/src/rules/no-insecure-redirects/index.js +0 -216
- package/src/rules/no-insecure-websocket/index.d.ts +0 -6
- package/src/rules/no-insecure-websocket/index.js +0 -61
- package/src/rules/no-missing-cors-check/index.d.ts +0 -9
- package/src/rules/no-missing-cors-check/index.js +0 -399
- package/src/rules/no-missing-csrf-protection/index.d.ts +0 -11
- package/src/rules/no-missing-csrf-protection/index.js +0 -180
- package/src/rules/no-missing-security-headers/index.d.ts +0 -7
- package/src/rules/no-missing-security-headers/index.js +0 -218
- package/src/rules/no-password-in-url/index.d.ts +0 -8
- package/src/rules/no-password-in-url/index.js +0 -54
- package/src/rules/no-permissive-cors/index.d.ts +0 -8
- package/src/rules/no-permissive-cors/index.js +0 -65
- package/src/rules/no-sensitive-data-in-analytics/index.d.ts +0 -8
- package/src/rules/no-sensitive-data-in-analytics/index.js +0 -62
- package/src/rules/no-sensitive-data-in-cache/index.d.ts +0 -8
- package/src/rules/no-sensitive-data-in-cache/index.js +0 -52
- package/src/rules/no-toctou-vulnerability/index.d.ts +0 -7
- package/src/rules/no-toctou-vulnerability/index.js +0 -208
- package/src/rules/no-tracking-without-consent/index.d.ts +0 -6
- package/src/rules/no-tracking-without-consent/index.js +0 -67
- package/src/rules/no-unencrypted-transmission/index.d.ts +0 -11
- package/src/rules/no-unencrypted-transmission/index.js +0 -236
- package/src/rules/no-unescaped-url-parameter/index.d.ts +0 -9
- package/src/rules/no-unescaped-url-parameter/index.js +0 -355
- package/src/rules/no-unsafe-dynamic-require/index.d.ts +0 -5
- package/src/rules/no-unsafe-dynamic-require/index.js +0 -106
- package/src/rules/no-unvalidated-deeplinks/index.d.ts +0 -6
- package/src/rules/no-unvalidated-deeplinks/index.js +0 -62
- package/src/rules/no-unvalidated-user-input/index.d.ts +0 -9
- package/src/rules/no-unvalidated-user-input/index.js +0 -420
- package/src/rules/no-verbose-error-messages/index.d.ts +0 -8
- package/src/rules/no-verbose-error-messages/index.js +0 -68
- package/src/rules/no-zip-slip/index.d.ts +0 -9
- package/src/rules/no-zip-slip/index.js +0 -445
- package/src/rules/require-code-minification/index.d.ts +0 -8
- package/src/rules/require-code-minification/index.js +0 -47
- package/src/rules/require-csp-headers/index.d.ts +0 -6
- package/src/rules/require-csp-headers/index.js +0 -64
- package/src/rules/require-data-minimization/index.d.ts +0 -8
- package/src/rules/require-data-minimization/index.js +0 -53
- package/src/rules/require-dependency-integrity/index.d.ts +0 -6
- package/src/rules/require-dependency-integrity/index.js +0 -64
- package/src/rules/require-https-only/index.d.ts +0 -8
- package/src/rules/require-https-only/index.js +0 -62
- package/src/rules/require-mime-type-validation/index.d.ts +0 -6
- package/src/rules/require-mime-type-validation/index.js +0 -66
- package/src/rules/require-network-timeout/index.d.ts +0 -8
- package/src/rules/require-network-timeout/index.js +0 -50
- package/src/rules/require-package-lock/index.d.ts +0 -8
- package/src/rules/require-package-lock/index.js +0 -63
- package/src/rules/require-secure-credential-storage/index.d.ts +0 -8
- package/src/rules/require-secure-credential-storage/index.js +0 -50
- package/src/rules/require-secure-deletion/index.d.ts +0 -8
- package/src/rules/require-secure-deletion/index.js +0 -44
- package/src/rules/require-storage-encryption/index.d.ts +0 -8
- package/src/rules/require-storage-encryption/index.js +0 -50
- package/src/rules/require-url-validation/index.d.ts +0 -6
- package/src/rules/require-url-validation/index.js +0 -72
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noMissingSecurityHeaders = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
6
|
-
const DEFAULT_REQUIRED_HEADERS = [
|
|
7
|
-
'Content-Security-Policy',
|
|
8
|
-
'X-Frame-Options',
|
|
9
|
-
'X-Content-Type-Options',
|
|
10
|
-
];
|
|
11
|
-
/**
|
|
12
|
-
* Extract header name from setHeader call
|
|
13
|
-
*/
|
|
14
|
-
function extractHeaderName(node) {
|
|
15
|
-
if (node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
|
|
16
|
-
return String(node.arguments[0].value);
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Check if all security headers are set in the current scope
|
|
22
|
-
*/
|
|
23
|
-
function checkFunctionForSecurityHeaders(node, requiredHeaders, context) {
|
|
24
|
-
const setHeaders = new Set();
|
|
25
|
-
// Find the function that contains this setHeader call
|
|
26
|
-
let current = node;
|
|
27
|
-
let scopeNode = null;
|
|
28
|
-
while (current) {
|
|
29
|
-
if (current.type === 'FunctionDeclaration' ||
|
|
30
|
-
current.type === 'FunctionExpression' ||
|
|
31
|
-
current.type === 'ArrowFunctionExpression') {
|
|
32
|
-
scopeNode = current;
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
current = current.parent ?? null;
|
|
36
|
-
}
|
|
37
|
-
// If no function found, use the program scope (for test cases)
|
|
38
|
-
if (!scopeNode) {
|
|
39
|
-
scopeNode = context.sourceCode.ast;
|
|
40
|
-
}
|
|
41
|
-
// Collect all setHeader calls in this scope
|
|
42
|
-
function collectHeaders(node) {
|
|
43
|
-
if (node.type === 'CallExpression' &&
|
|
44
|
-
node.callee.type === 'MemberExpression' &&
|
|
45
|
-
node.callee.property.type === 'Identifier' &&
|
|
46
|
-
['setHeader', 'header', 'set'].includes(node.callee.property.name)) {
|
|
47
|
-
const headerName = extractHeaderName(node);
|
|
48
|
-
if (headerName) {
|
|
49
|
-
setHeaders.add(headerName);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Recursively check children - only traverse standard AST properties
|
|
53
|
-
if (node.type === 'Program' && node.body) {
|
|
54
|
-
node.body.forEach(collectHeaders);
|
|
55
|
-
}
|
|
56
|
-
else if ((node.type === 'FunctionDeclaration' ||
|
|
57
|
-
node.type === 'FunctionExpression' ||
|
|
58
|
-
node.type === 'ArrowFunctionExpression') && node.body) {
|
|
59
|
-
collectHeaders(node.body);
|
|
60
|
-
}
|
|
61
|
-
else if (node.type === 'BlockStatement' && node.body) {
|
|
62
|
-
node.body.forEach(collectHeaders);
|
|
63
|
-
}
|
|
64
|
-
else if (node.type === 'ExpressionStatement' && node.expression) {
|
|
65
|
-
collectHeaders(node.expression);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (scopeNode) {
|
|
69
|
-
collectHeaders(scopeNode);
|
|
70
|
-
}
|
|
71
|
-
// Return missing headers
|
|
72
|
-
return requiredHeaders.filter(header => !setHeaders.has(header));
|
|
73
|
-
}
|
|
74
|
-
exports.noMissingSecurityHeaders = (0, eslint_devkit_2.createRule)({
|
|
75
|
-
name: 'no-missing-security-headers',
|
|
76
|
-
meta: {
|
|
77
|
-
type: 'problem',
|
|
78
|
-
deprecated: true,
|
|
79
|
-
replacedBy: ['@see eslint-plugin-express-security/require-helmet'],
|
|
80
|
-
docs: {
|
|
81
|
-
description: 'Detects missing security headers in HTTP responses',
|
|
82
|
-
},
|
|
83
|
-
hasSuggestions: true,
|
|
84
|
-
messages: {
|
|
85
|
-
missingSecurityHeader: (0, eslint_devkit_1.formatLLMMessage)({
|
|
86
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
87
|
-
issueName: 'Missing security headers',
|
|
88
|
-
cwe: 'CWE-693',
|
|
89
|
-
description: 'Missing security headers: {{headers}}',
|
|
90
|
-
severity: 'HIGH',
|
|
91
|
-
fix: 'Set security headers: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options',
|
|
92
|
-
documentationLink: 'https://owasp.org/www-project-secure-headers/',
|
|
93
|
-
}),
|
|
94
|
-
addSecurityHeaders: (0, eslint_devkit_1.formatLLMMessage)({
|
|
95
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
96
|
-
issueName: 'Add Security Headers',
|
|
97
|
-
description: 'Add security headers middleware',
|
|
98
|
-
severity: 'LOW',
|
|
99
|
-
fix: 'Add Content-Security-Policy, X-Frame-Options headers',
|
|
100
|
-
documentationLink: 'https://owasp.org/www-project-secure-headers/',
|
|
101
|
-
}),
|
|
102
|
-
useMiddleware: (0, eslint_devkit_1.formatLLMMessage)({
|
|
103
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
104
|
-
issueName: 'Use Helmet',
|
|
105
|
-
description: 'Use helmet.js for security headers',
|
|
106
|
-
severity: 'LOW',
|
|
107
|
-
fix: 'app.use(helmet())',
|
|
108
|
-
documentationLink: 'https://helmetjs.github.io/',
|
|
109
|
-
}),
|
|
110
|
-
setHeader: (0, eslint_devkit_1.formatLLMMessage)({
|
|
111
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
112
|
-
issueName: 'Set Headers',
|
|
113
|
-
description: 'Set security headers manually',
|
|
114
|
-
severity: 'LOW',
|
|
115
|
-
fix: 'res.setHeader("X-Frame-Options", "DENY")',
|
|
116
|
-
documentationLink: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers',
|
|
117
|
-
}),
|
|
118
|
-
},
|
|
119
|
-
schema: [
|
|
120
|
-
{
|
|
121
|
-
type: 'object',
|
|
122
|
-
properties: {
|
|
123
|
-
requiredHeaders: {
|
|
124
|
-
type: 'array',
|
|
125
|
-
items: { type: 'string' },
|
|
126
|
-
default: DEFAULT_REQUIRED_HEADERS,
|
|
127
|
-
},
|
|
128
|
-
ignoreInTests: {
|
|
129
|
-
type: 'boolean',
|
|
130
|
-
default: true,
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
additionalProperties: false,
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
},
|
|
137
|
-
defaultOptions: [
|
|
138
|
-
{
|
|
139
|
-
requiredHeaders: DEFAULT_REQUIRED_HEADERS,
|
|
140
|
-
ignoreInTests: true,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
create(context, [options = {}]) {
|
|
144
|
-
const { requiredHeaders = DEFAULT_REQUIRED_HEADERS, ignoreInTests = true, } = options || {};
|
|
145
|
-
const filename = context.getFilename();
|
|
146
|
-
const isTestFile = ignoreInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
147
|
-
if (isTestFile) {
|
|
148
|
-
return {};
|
|
149
|
-
}
|
|
150
|
-
const reportedScopes = new Set();
|
|
151
|
-
/**
|
|
152
|
-
* Get a unique key for the current scope
|
|
153
|
-
*/
|
|
154
|
-
function getScopeKey(node) {
|
|
155
|
-
// Find the function that contains this call
|
|
156
|
-
let current = node;
|
|
157
|
-
while (current) {
|
|
158
|
-
if (current.type === 'FunctionDeclaration' ||
|
|
159
|
-
current.type === 'FunctionExpression' ||
|
|
160
|
-
current.type === 'ArrowFunctionExpression') {
|
|
161
|
-
return `${current.range?.[0]}-${current.range?.[1]}`;
|
|
162
|
-
}
|
|
163
|
-
current = current.parent ?? null;
|
|
164
|
-
}
|
|
165
|
-
// If no function found, use program scope
|
|
166
|
-
return 'program';
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Check for response header setting
|
|
170
|
-
*/
|
|
171
|
-
function checkCallExpression(node) {
|
|
172
|
-
// Check for res.setHeader, res.header, res.set
|
|
173
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
174
|
-
node.callee.property.type === 'Identifier') {
|
|
175
|
-
const methodName = node.callee.property.name;
|
|
176
|
-
if (['setHeader', 'header', 'set'].includes(methodName)) {
|
|
177
|
-
const scopeKey = getScopeKey(node);
|
|
178
|
-
// Only check once per scope
|
|
179
|
-
if (reportedScopes.has(scopeKey)) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
const missing = checkFunctionForSecurityHeaders(node, requiredHeaders, context);
|
|
183
|
-
if (missing.length > 0) {
|
|
184
|
-
reportedScopes.add(scopeKey);
|
|
185
|
-
context.report({
|
|
186
|
-
node,
|
|
187
|
-
messageId: 'missingSecurityHeader',
|
|
188
|
-
data: {
|
|
189
|
-
headers: missing.join(', '),
|
|
190
|
-
},
|
|
191
|
-
suggest: [
|
|
192
|
-
{
|
|
193
|
-
messageId: 'addSecurityHeaders',
|
|
194
|
-
fix: () => null,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
messageId: 'useMiddleware',
|
|
198
|
-
fix: () => null,
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
messageId: 'setHeader',
|
|
202
|
-
fix: () => null,
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
// Mark as checked even if no error
|
|
209
|
-
reportedScopes.add(scopeKey);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
CallExpression: checkCallExpression,
|
|
216
|
-
};
|
|
217
|
-
},
|
|
218
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Prevent passwords in URLs
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/598.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const noPasswordInUrl: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Prevent passwords in URLs
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/598.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.noPasswordInUrl = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.noPasswordInUrl = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'no-password-in-url',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Prevent passwords in URLs',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M3'],
|
|
19
|
-
cweIds: ["CWE-598"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-521',
|
|
26
|
-
description: 'Prevent passwords in URLs detected - this is a security risk',
|
|
27
|
-
severity: 'CRITICAL',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/521.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
function report(node) {
|
|
37
|
-
context.report({
|
|
38
|
-
node,
|
|
39
|
-
messageId: 'violationDetected',
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
Literal(node) {
|
|
44
|
-
// Check for http://user:password@host patterns
|
|
45
|
-
if (node.type === 'Literal' && typeof node.value === 'string') {
|
|
46
|
-
const urlPattern = /https?:\/\/[^:]+:[^@]+@/;
|
|
47
|
-
if (urlPattern.test(node.value)) {
|
|
48
|
-
report(node);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
},
|
|
54
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Prevent overly permissive CORS configuration
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/942.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const noPermissiveCors: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Prevent overly permissive CORS configuration
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/942.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.noPermissiveCors = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.noPermissiveCors = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'no-permissive-cors',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
deprecated: true,
|
|
15
|
-
replacedBy: ['@see eslint-plugin-express-security/no-permissive-cors'],
|
|
16
|
-
docs: {
|
|
17
|
-
description: 'Prevent overly permissive CORS configuration',
|
|
18
|
-
category: 'Security',
|
|
19
|
-
recommended: true,
|
|
20
|
-
owaspMobile: ['M8'],
|
|
21
|
-
cweIds: ["CWE-942"],
|
|
22
|
-
},
|
|
23
|
-
messages: {
|
|
24
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
25
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
26
|
-
issueName: 'violation Detected',
|
|
27
|
-
cwe: 'CWE-942',
|
|
28
|
-
description: 'Prevent overly permissive CORS configuration detected - this is a security risk',
|
|
29
|
-
severity: 'HIGH',
|
|
30
|
-
fix: 'Review and apply secure practices',
|
|
31
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/942.html',
|
|
32
|
-
})
|
|
33
|
-
},
|
|
34
|
-
schema: [],
|
|
35
|
-
},
|
|
36
|
-
defaultOptions: [],
|
|
37
|
-
create(context) {
|
|
38
|
-
function report(node) {
|
|
39
|
-
context.report({
|
|
40
|
-
node,
|
|
41
|
-
messageId: 'violationDetected',
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
CallExpression(node) {
|
|
46
|
-
// Check for Access-Control-Allow-Origin: *
|
|
47
|
-
if (node.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
48
|
-
node.callee.property?.name === 'setHeader' &&
|
|
49
|
-
node.arguments[0]?.value === 'Access-Control-Allow-Origin' &&
|
|
50
|
-
node.arguments[1]?.value === '*') {
|
|
51
|
-
report(node);
|
|
52
|
-
}
|
|
53
|
-
// Check cors({ origin: '*' })
|
|
54
|
-
if (node.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression &&
|
|
55
|
-
node.callee.name === 'cors' &&
|
|
56
|
-
node.arguments[0]?.type === eslint_devkit_1.AST_NODE_TYPES.ObjectExpression) {
|
|
57
|
-
const originProp = node.arguments[0].properties.find(p => p.key?.name === 'origin');
|
|
58
|
-
if (originProp?.value.type === 'Literal' && originProp.value.value === '*') {
|
|
59
|
-
report(node);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
},
|
|
65
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Prevent PII sent to analytics
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/359.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const noSensitiveDataInAnalytics: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Prevent PII sent to analytics
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/359.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.noSensitiveDataInAnalytics = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.noSensitiveDataInAnalytics = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'no-sensitive-data-in-analytics',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Prevent PII being sent to analytics services',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M6'],
|
|
19
|
-
cweIds: ['CWE-359'],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'Sensitive Data in Analytics',
|
|
25
|
-
cwe: 'CWE-359',
|
|
26
|
-
description: 'Sensitive field sent to analytics - this is a privacy violation',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Remove PII from analytics tracking data',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/359.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
const sensitiveFields = ['email', 'ssn', 'creditcard', 'password', 'phone', 'address'];
|
|
37
|
-
function report(node, field) {
|
|
38
|
-
context.report({ node, messageId: 'violationDetected', data: { field } });
|
|
39
|
-
}
|
|
40
|
-
return {
|
|
41
|
-
CallExpression(node) {
|
|
42
|
-
// analytics.track() with sensitive data
|
|
43
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
44
|
-
node.callee.object.name === 'analytics' &&
|
|
45
|
-
node.callee.property.name === 'track') {
|
|
46
|
-
const dataArg = node.arguments[1];
|
|
47
|
-
if (dataArg?.type === 'ObjectExpression') {
|
|
48
|
-
dataArg.properties.forEach(prop => {
|
|
49
|
-
if (prop.type === 'Property') {
|
|
50
|
-
const key = prop.key.name?.toLowerCase();
|
|
51
|
-
const matchedField = sensitiveFields.find(f => key?.includes(f));
|
|
52
|
-
if (matchedField) {
|
|
53
|
-
report(prop, matchedField);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Prevent caching sensitive data without encryption
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/524.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const noSensitiveDataInCache: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Prevent caching sensitive data without encryption
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/524.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.noSensitiveDataInCache = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.noSensitiveDataInCache = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'no-sensitive-data-in-cache',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Prevent caching sensitive data without encryption',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M9'],
|
|
19
|
-
cweIds: ["CWE-524"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-200',
|
|
26
|
-
description: 'Prevent caching sensitive data without encryption detected - Sensitive data in cache',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/200.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
return {
|
|
37
|
-
CallExpression(node) {
|
|
38
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
39
|
-
node.callee.property.type === 'Identifier' &&
|
|
40
|
-
['set', 'put', 'store'].includes(node.callee.property.name)) {
|
|
41
|
-
const keyArg = node.arguments[0];
|
|
42
|
-
if (keyArg && keyArg.type === 'Literal') {
|
|
43
|
-
const key = keyArg.value.toString().toLowerCase();
|
|
44
|
-
if (['password', 'token', 'credit', 'ssn'].some(k => key.includes(k))) {
|
|
45
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface Options {
|
|
2
|
-
/** Ignore in test files. Default: true */
|
|
3
|
-
ignoreInTests?: boolean;
|
|
4
|
-
/** File system methods to check. Default: ['fs.existsSync', 'fs.statSync', 'fs.accessSync'] */
|
|
5
|
-
fsMethods?: string[];
|
|
6
|
-
}
|
|
7
|
-
export declare const noToctouVulnerability: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|