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,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,6 +0,0 @@
1
- /**
2
- * @fileoverview Require MIME type validation for uploads
3
- */
4
- export interface Options {
5
- }
6
- export declare const requireMimeTypeValidation: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -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,6 +0,0 @@
1
- /**
2
- * @fileoverview Enforce URL validation before navigation
3
- */
4
- export interface Options {
5
- }
6
- export declare const requireUrlValidation: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -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
- });