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,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Require integrity hashes for external resources
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.requireDependencyIntegrity = void 0;
|
|
7
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
8
|
-
exports.requireDependencyIntegrity = (0, eslint_devkit_1.createRule)({
|
|
9
|
-
name: 'require-dependency-integrity',
|
|
10
|
-
meta: {
|
|
11
|
-
type: 'problem',
|
|
12
|
-
docs: {
|
|
13
|
-
description: 'Require SRI (Subresource Integrity) for CDN resources',
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
18
|
-
issueName: 'Missing SRI',
|
|
19
|
-
cwe: 'CWE-494',
|
|
20
|
-
description: 'External resource loaded without integrity hash - supply chain risk',
|
|
21
|
-
severity: 'HIGH',
|
|
22
|
-
fix: 'Add integrity="sha384-..." and crossorigin="anonymous" attributes',
|
|
23
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/494.html',
|
|
24
|
-
})
|
|
25
|
-
},
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
defaultOptions: [],
|
|
29
|
-
create(context) {
|
|
30
|
-
function report(node) {
|
|
31
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
Literal(node) {
|
|
35
|
-
if (typeof node.value !== 'string')
|
|
36
|
-
return;
|
|
37
|
-
// Check for script/link tags without integrity
|
|
38
|
-
const value = node.value.toLowerCase();
|
|
39
|
-
if ((value.includes('<script') && value.includes('src=')) ||
|
|
40
|
-
(value.includes('<link') && value.includes('href='))) {
|
|
41
|
-
// Check if CDN source
|
|
42
|
-
if (value.includes('cdn.') || value.includes('cdnjs.') ||
|
|
43
|
-
value.includes('unpkg.') || value.includes('jsdelivr.')) {
|
|
44
|
-
if (!value.includes('integrity=')) {
|
|
45
|
-
report(node);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
TemplateLiteral(node) {
|
|
51
|
-
const text = context.sourceCode.getText(node).toLowerCase();
|
|
52
|
-
if ((text.includes('<script') && text.includes('src=')) ||
|
|
53
|
-
(text.includes('<link') && text.includes('href='))) {
|
|
54
|
-
if (text.includes('cdn.') || text.includes('cdnjs.') ||
|
|
55
|
-
text.includes('unpkg.') || text.includes('jsdelivr.')) {
|
|
56
|
-
if (!text.includes('integrity=')) {
|
|
57
|
-
report(node);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Enforce HTTPS for all external requests
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/319.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requireHttpsOnly: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Enforce HTTPS for all external requests
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/319.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requireHttpsOnly = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requireHttpsOnly = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-https-only',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Enforce HTTPS for all external requests',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M5'],
|
|
19
|
-
cweIds: ["CWE-319"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-319',
|
|
26
|
-
description: 'Enforce HTTPS for all external requests detected - this is a security risk',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/319.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
|
-
CallExpression(node) {
|
|
44
|
-
// Check fetch/axios calls with http:// URLs
|
|
45
|
-
if (node.type === 'CallExpression') {
|
|
46
|
-
const callee = node.callee;
|
|
47
|
-
const isHttpCall = (callee.name === 'fetch' ||
|
|
48
|
-
(callee.object?.name === 'axios' &&
|
|
49
|
-
['get', 'post', 'put', 'delete', 'patch'].includes(callee.property?.name)));
|
|
50
|
-
if (isHttpCall && node.arguments[0]) {
|
|
51
|
-
const url = node.arguments[0];
|
|
52
|
-
if (url.type === 'Literal' &&
|
|
53
|
-
typeof url.value === 'string' &&
|
|
54
|
-
url.value.startsWith('http://')) {
|
|
55
|
-
report(node);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
});
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Require MIME type validation for uploads
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.requireMimeTypeValidation = void 0;
|
|
7
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
8
|
-
exports.requireMimeTypeValidation = (0, eslint_devkit_1.createRule)({
|
|
9
|
-
name: 'require-mime-type-validation',
|
|
10
|
-
meta: {
|
|
11
|
-
type: 'problem',
|
|
12
|
-
docs: {
|
|
13
|
-
description: 'Require MIME type validation for file uploads',
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
18
|
-
issueName: 'Missing MIME Validation',
|
|
19
|
-
cwe: 'CWE-434',
|
|
20
|
-
description: 'File upload without MIME type validation - unrestricted upload vulnerability',
|
|
21
|
-
severity: 'HIGH',
|
|
22
|
-
fix: 'Add fileFilter option to validate MIME types',
|
|
23
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/434.html',
|
|
24
|
-
})
|
|
25
|
-
},
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
defaultOptions: [],
|
|
29
|
-
create(context) {
|
|
30
|
-
function report(node) {
|
|
31
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
CallExpression(node) {
|
|
35
|
-
// Detect multer().single() or multer().array() without fileFilter
|
|
36
|
-
if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
|
|
37
|
-
node.callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
|
|
38
|
-
['single', 'array', 'fields'].includes(node.callee.property.name)) {
|
|
39
|
-
// Check if parent has fileFilter configuration
|
|
40
|
-
const calleeObj = node.callee.object;
|
|
41
|
-
if (calleeObj.type === eslint_devkit_1.AST_NODE_TYPES.CallExpression) {
|
|
42
|
-
const multerArgs = calleeObj.arguments[0];
|
|
43
|
-
if (multerArgs && multerArgs.type === eslint_devkit_1.AST_NODE_TYPES.ObjectExpression) {
|
|
44
|
-
const hasFileFilter = multerArgs.properties.some((p) => p.type === eslint_devkit_1.AST_NODE_TYPES.Property && p.key.type === eslint_devkit_1.AST_NODE_TYPES.Identifier && (p.key.name === 'fileFilter' || p.key.name === 'limits'));
|
|
45
|
-
if (!hasFileFilter) {
|
|
46
|
-
report(node);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else if (!multerArgs) {
|
|
50
|
-
// No config at all = no validation
|
|
51
|
-
report(node);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
// Detect upload() calls directly
|
|
56
|
-
if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier && node.callee.name === 'upload') {
|
|
57
|
-
// Check if there's validation in arguments
|
|
58
|
-
if (node.arguments.length === 0 ||
|
|
59
|
-
(node.arguments[0]?.type === eslint_devkit_1.AST_NODE_TYPES.Identifier)) {
|
|
60
|
-
report(node);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Require timeout limits for network requests
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/770.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requireNetworkTimeout: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Require timeout limits for network requests
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/770.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requireNetworkTimeout = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requireNetworkTimeout = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-network-timeout',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Require timeout limits for network requests',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M5'],
|
|
19
|
-
cweIds: ["CWE-770"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-400',
|
|
26
|
-
description: 'Require timeout limits for network requests detected - fetch/axios without timeout option',
|
|
27
|
-
severity: 'MEDIUM',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/400.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
return {
|
|
37
|
-
CallExpression(node) {
|
|
38
|
-
if (node.callee.name === 'fetch' ||
|
|
39
|
-
(node.callee.type === 'MemberExpression' &&
|
|
40
|
-
node.callee.object.name === 'axios')) {
|
|
41
|
-
const hasTimeout = node.arguments[1]?.type === 'ObjectExpression' &&
|
|
42
|
-
node.arguments[1].properties.some(p => p.key?.name === 'timeout');
|
|
43
|
-
if (!hasTimeout) {
|
|
44
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Ensure package lock file exists
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/829.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requirePackageLock: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Ensure package lock file exists
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/829.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requirePackageLock = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requirePackageLock = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-package-lock',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'suggestion',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Ensure package-lock.json or yarn.lock exists',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M2'],
|
|
19
|
-
cweIds: ['CWE-829'],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-829',
|
|
26
|
-
description: 'Package lock file missing - commit package-lock',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/829.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
const fs = require('node:fs');
|
|
37
|
-
const path = require('node:path');
|
|
38
|
-
// Check once per file
|
|
39
|
-
let checked = false;
|
|
40
|
-
return {
|
|
41
|
-
Program(node) {
|
|
42
|
-
if (checked)
|
|
43
|
-
return;
|
|
44
|
-
checked = true;
|
|
45
|
-
// Find project root (simplified)
|
|
46
|
-
let dir = path.dirname(context.filename);
|
|
47
|
-
let found = false;
|
|
48
|
-
for (let i = 0; i < 10; i++) {
|
|
49
|
-
if (fs.existsSync(path.join(dir, 'package-lock.json')) ||
|
|
50
|
-
fs.existsSync(path.join(dir, 'yarn.lock')) ||
|
|
51
|
-
fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))) {
|
|
52
|
-
found = true;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
dir = path.dirname(dir);
|
|
56
|
-
}
|
|
57
|
-
if (!found) {
|
|
58
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
},
|
|
63
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Enforce secure storage patterns for credentials
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/522.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requireSecureCredentialStorage: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Enforce secure storage patterns for credentials
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/522.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requireSecureCredentialStorage = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requireSecureCredentialStorage = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-secure-credential-storage',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Enforce secure storage patterns for credentials',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M1'],
|
|
19
|
-
cweIds: ["CWE-522"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-312',
|
|
26
|
-
description: 'Enforce secure storage patterns for credentials detected - Credentials without encryption',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/312.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
return {
|
|
37
|
-
CallExpression(node) {
|
|
38
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
39
|
-
['setItem', 'writeFile'].includes(node.callee.property.name)) {
|
|
40
|
-
// Check for encryption wrapper
|
|
41
|
-
const hasEncryption = node.arguments.some(arg => arg.type === 'CallExpression' &&
|
|
42
|
-
arg.callee.name?.includes('encrypt'));
|
|
43
|
-
if (!hasEncryption) {
|
|
44
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Require secure data deletion patterns
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/459.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requireSecureDeletion: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Require secure data deletion patterns
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/459.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requireSecureDeletion = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requireSecureDeletion = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-secure-deletion',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Require secure data deletion patterns',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M9'],
|
|
19
|
-
cweIds: ["CWE-459"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-459',
|
|
26
|
-
description: 'Require secure data deletion patterns detected - delete without secure wipe',
|
|
27
|
-
severity: 'MEDIUM',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/459.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
return {
|
|
37
|
-
UnaryExpression(node) {
|
|
38
|
-
if (node.operator === 'delete') {
|
|
39
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Require encryption for persistent storage
|
|
3
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
4
|
-
* @see https://cwe.mitre.org/data/definitions/311.html
|
|
5
|
-
*/
|
|
6
|
-
export interface Options {
|
|
7
|
-
}
|
|
8
|
-
export declare const requireStorageEncryption: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Require encryption for persistent storage
|
|
4
|
-
* @see https://owasp.org/www-project-mobile-top-10/
|
|
5
|
-
* @see https://cwe.mitre.org/data/definitions/311.html
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.requireStorageEncryption = void 0;
|
|
9
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
-
exports.requireStorageEncryption = (0, eslint_devkit_1.createRule)({
|
|
11
|
-
name: 'require-storage-encryption',
|
|
12
|
-
meta: {
|
|
13
|
-
type: 'problem',
|
|
14
|
-
docs: {
|
|
15
|
-
description: 'Require encryption for persistent storage',
|
|
16
|
-
category: 'Security',
|
|
17
|
-
recommended: true,
|
|
18
|
-
owaspMobile: ['M9'],
|
|
19
|
-
cweIds: ["CWE-311"],
|
|
20
|
-
},
|
|
21
|
-
messages: {
|
|
22
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
23
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
24
|
-
issueName: 'violation Detected',
|
|
25
|
-
cwe: 'CWE-312',
|
|
26
|
-
description: 'Require encryption for persistent storage detected - Storage without encryption',
|
|
27
|
-
severity: 'HIGH',
|
|
28
|
-
fix: 'Review and apply secure practices',
|
|
29
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/312.html',
|
|
30
|
-
})
|
|
31
|
-
},
|
|
32
|
-
schema: [],
|
|
33
|
-
},
|
|
34
|
-
defaultOptions: [],
|
|
35
|
-
create(context) {
|
|
36
|
-
return {
|
|
37
|
-
CallExpression(node) {
|
|
38
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
39
|
-
['setItem', 'writeFile'].includes(node.callee.property.name)) {
|
|
40
|
-
// Check for encryption wrapper
|
|
41
|
-
const hasEncryption = node.arguments.some(arg => arg.type === 'CallExpression' &&
|
|
42
|
-
arg.callee.name?.includes('encrypt'));
|
|
43
|
-
if (!hasEncryption) {
|
|
44
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
},
|
|
50
|
-
});
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @fileoverview Enforce URL validation before navigation
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.requireUrlValidation = void 0;
|
|
7
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
8
|
-
exports.requireUrlValidation = (0, eslint_devkit_1.createRule)({
|
|
9
|
-
name: 'require-url-validation',
|
|
10
|
-
meta: {
|
|
11
|
-
type: 'problem',
|
|
12
|
-
docs: {
|
|
13
|
-
description: 'Enforce URL validation before navigation',
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
violationDetected: (0, eslint_devkit_1.formatLLMMessage)({
|
|
17
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
18
|
-
issueName: 'URL Validation Required',
|
|
19
|
-
cwe: 'CWE-601',
|
|
20
|
-
description: 'Unvalidated URL used for navigation - this is a security risk',
|
|
21
|
-
severity: 'HIGH',
|
|
22
|
-
fix: 'Validate URLs before using them for navigation',
|
|
23
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/601.html',
|
|
24
|
-
})
|
|
25
|
-
},
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
defaultOptions: [],
|
|
29
|
-
create(context) {
|
|
30
|
-
function report(node) {
|
|
31
|
-
context.report({ node, messageId: 'violationDetected' });
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
AssignmentExpression(node) {
|
|
35
|
-
// Detect window.location assignment from user input
|
|
36
|
-
if (node.left.type === 'MemberExpression' &&
|
|
37
|
-
node.left.object.type === 'Identifier' &&
|
|
38
|
-
node.left.object.name === 'window' &&
|
|
39
|
-
node.left.property.type === 'Identifier' &&
|
|
40
|
-
node.left.property.name === 'location') {
|
|
41
|
-
// Flag if right side is a variable (not a literal URL)
|
|
42
|
-
if (node.right.type === 'Identifier') {
|
|
43
|
-
report(node);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// Detect location.href assignment
|
|
47
|
-
if (node.left.type === 'MemberExpression' &&
|
|
48
|
-
node.left.object.type === 'Identifier' &&
|
|
49
|
-
node.left.object.name === 'location' &&
|
|
50
|
-
node.left.property.type === 'Identifier' &&
|
|
51
|
-
node.left.property.name === 'href') {
|
|
52
|
-
if (node.right.type === 'Identifier') {
|
|
53
|
-
report(node);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
CallExpression(node) {
|
|
58
|
-
// Detect window.open with variable URL
|
|
59
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
60
|
-
node.callee.object.type === 'Identifier' &&
|
|
61
|
-
node.callee.object.name === 'window' &&
|
|
62
|
-
node.callee.property.type === 'Identifier' &&
|
|
63
|
-
node.callee.property.name === 'open') {
|
|
64
|
-
const urlArg = node.arguments[0];
|
|
65
|
-
if (urlArg && urlArg.type === 'Identifier') {
|
|
66
|
-
report(node);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
});
|