@sfdxy/mule-lint 1.20.0 → 1.21.0

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 (134) hide show
  1. package/README.md +63 -17
  2. package/dist/package.json +1 -1
  3. package/dist/src/core/XPathHelper.d.ts.map +1 -1
  4. package/dist/src/core/XPathHelper.js +8 -0
  5. package/dist/src/core/XPathHelper.js.map +1 -1
  6. package/dist/src/engine/LintEngine.d.ts +22 -0
  7. package/dist/src/engine/LintEngine.d.ts.map +1 -1
  8. package/dist/src/engine/LintEngine.js +105 -18
  9. package/dist/src/engine/LintEngine.js.map +1 -1
  10. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts +22 -0
  11. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts.map +1 -0
  12. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js +43 -0
  13. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js.map +1 -0
  14. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts +24 -0
  15. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts.map +1 -0
  16. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js +53 -0
  17. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js.map +1 -0
  18. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts +25 -0
  19. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts.map +1 -0
  20. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js +59 -0
  21. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js.map +1 -0
  22. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts +24 -0
  23. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts.map +1 -0
  24. package/dist/src/rules/connector/EventListenerNullGuardRule.js +58 -0
  25. package/dist/src/rules/connector/EventListenerNullGuardRule.js.map +1 -0
  26. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts +23 -0
  27. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts.map +1 -0
  28. package/dist/src/rules/connector/ReplayChannelConfigRule.js +52 -0
  29. package/dist/src/rules/connector/ReplayChannelConfigRule.js.map +1 -0
  30. package/dist/src/rules/dataweave/DataWeaveRules.d.ts +11 -4
  31. package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
  32. package/dist/src/rules/dataweave/DataWeaveRules.js +20 -20
  33. package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
  34. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts +25 -0
  35. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts.map +1 -0
  36. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js +63 -0
  37. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js.map +1 -0
  38. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts +24 -0
  39. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts.map +1 -0
  40. package/dist/src/rules/error-handling/CatchAllLastRule.js +65 -0
  41. package/dist/src/rules/error-handling/CatchAllLastRule.js.map +1 -0
  42. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts +28 -0
  43. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts.map +1 -0
  44. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js +70 -0
  45. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js.map +1 -0
  46. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts +23 -0
  47. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts.map +1 -0
  48. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js +73 -0
  49. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js.map +1 -0
  50. package/dist/src/rules/error-handling/GenericErrorRule.d.ts +15 -3
  51. package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
  52. package/dist/src/rules/error-handling/GenericErrorRule.js +58 -18
  53. package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
  54. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +14 -15
  55. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
  56. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +59 -38
  57. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
  58. package/dist/src/rules/error-handling/TryScopeRule.d.ts +5 -0
  59. package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
  60. package/dist/src/rules/error-handling/TryScopeRule.js +30 -7
  61. package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
  62. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts +27 -0
  63. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts.map +1 -0
  64. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js +46 -0
  65. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js.map +1 -0
  66. package/dist/src/rules/index.d.ts +1 -1
  67. package/dist/src/rules/index.d.ts.map +1 -1
  68. package/dist/src/rules/index.js +50 -8
  69. package/dist/src/rules/index.js.map +1 -1
  70. package/dist/src/rules/logging/LoggerPayloadRule.d.ts +15 -0
  71. package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
  72. package/dist/src/rules/logging/LoggerPayloadRule.js +48 -4
  73. package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
  74. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts +23 -0
  75. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts.map +1 -0
  76. package/dist/src/rules/operations/FlowRefTargetExistsRule.js +58 -0
  77. package/dist/src/rules/operations/FlowRefTargetExistsRule.js.map +1 -0
  78. package/dist/src/rules/operations/UnusedFlowRule.d.ts +20 -0
  79. package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
  80. package/dist/src/rules/operations/UnusedFlowRule.js +73 -7
  81. package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
  82. package/dist/src/rules/operations/UnusedVariableRule.d.ts +31 -0
  83. package/dist/src/rules/operations/UnusedVariableRule.d.ts.map +1 -0
  84. package/dist/src/rules/operations/UnusedVariableRule.js +103 -0
  85. package/dist/src/rules/operations/UnusedVariableRule.js.map +1 -0
  86. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts +28 -0
  87. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts.map +1 -0
  88. package/dist/src/rules/performance/ListenerReconnectForeverRule.js +56 -0
  89. package/dist/src/rules/performance/ListenerReconnectForeverRule.js.map +1 -0
  90. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts +7 -4
  91. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
  92. package/dist/src/rules/performance/ReconnectionStrategyRule.js +44 -24
  93. package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
  94. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts +36 -0
  95. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts.map +1 -0
  96. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js +124 -0
  97. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js.map +1 -0
  98. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts +4 -0
  99. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
  100. package/dist/src/rules/security/HardcodedCredentialsRule.js +15 -0
  101. package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
  102. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts +25 -0
  103. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts.map +1 -0
  104. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js +59 -0
  105. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js.map +1 -0
  106. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts +23 -0
  107. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts.map +1 -0
  108. package/dist/src/rules/security/SecurePropertiesKeyRule.js +45 -0
  109. package/dist/src/rules/security/SecurePropertiesKeyRule.js.map +1 -0
  110. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts +25 -0
  111. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts.map +1 -0
  112. package/dist/src/rules/security/TlsKeystorePasswordRule.js +63 -0
  113. package/dist/src/rules/security/TlsKeystorePasswordRule.js.map +1 -0
  114. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts +26 -0
  115. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts.map +1 -0
  116. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js +61 -0
  117. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js.map +1 -0
  118. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts +34 -0
  119. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts.map +1 -0
  120. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js +76 -0
  121. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js.map +1 -0
  122. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts +25 -0
  123. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts.map +1 -0
  124. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js +111 -0
  125. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js.map +1 -0
  126. package/dist/src/rules/yaml/YamlRules.d.ts +6 -2
  127. package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
  128. package/dist/src/rules/yaml/YamlRules.js +15 -11
  129. package/dist/src/rules/yaml/YamlRules.js.map +1 -1
  130. package/dist/src/types/Rule.d.ts +13 -0
  131. package/dist/src/types/Rule.d.ts.map +1 -1
  132. package/docs/best-practices/rules-catalog.md +337 -29
  133. package/docs/linter/architecture.md +119 -64
  134. package/package.json +1 -1
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectorCredentialsSecuredRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * SEC-007: Connector Credentials Secured
7
+ *
8
+ * Salesforce, NetSuite, Database, and other connector configurations must
9
+ * use `${secure::...}` (not plain `${...}`) for credential attributes.
10
+ *
11
+ * Plain property placeholders like `${sf.password}` store the value in
12
+ * clear text in property files. The `${secure::...}` prefix ensures the
13
+ * value is read from an encrypted secure properties file.
14
+ *
15
+ * Covered connectors and attributes:
16
+ * - Salesforce: username, password, securityToken, consumerKey, consumerSecret
17
+ * - NetSuite: consumerKey, consumerSecret, tokenId, tokenSecret
18
+ * - Database: password, user (when not using connection URL)
19
+ * - HTTP Basic Auth: username, password
20
+ * - SMTP: password
21
+ */
22
+ class ConnectorCredentialsSecuredRule extends BaseRule_1.BaseRule {
23
+ id = 'SEC-007';
24
+ name = 'Connector Credentials Secured';
25
+ description = 'Connector credentials must use ${secure::} property placeholders';
26
+ severity = 'error';
27
+ category = 'security';
28
+ issueType = 'vulnerability';
29
+ /**
30
+ * Map of element local-name patterns to their sensitive attributes.
31
+ * We match on local-name() to be namespace-agnostic.
32
+ */
33
+ CONNECTOR_SENSITIVE_ATTRS = {
34
+ // Salesforce connector
35
+ 'sfdc-config': ['username', 'password', 'securityToken', 'consumerKey', 'consumerSecret'],
36
+ 'salesforce-config': ['username', 'password', 'securityToken', 'consumerKey', 'consumerSecret'],
37
+ 'basic-connection': [
38
+ 'username',
39
+ 'password',
40
+ 'securityToken',
41
+ 'consumerKey',
42
+ 'consumerSecret',
43
+ 'tokenId',
44
+ 'tokenSecret',
45
+ ],
46
+ 'oauth-user-pass-connection': ['consumerKey', 'consumerSecret'],
47
+ 'oauth-jwt-connection': ['consumerKey', 'keyStorePath', 'storePassword'],
48
+ // NetSuite connector (token-based)
49
+ 'token-based-authentication-connection': [
50
+ 'consumerKey',
51
+ 'consumerSecret',
52
+ 'tokenId',
53
+ 'tokenSecret',
54
+ ],
55
+ // Database connector
56
+ 'derby-connection': ['password'],
57
+ 'generic-connection': ['password'],
58
+ 'my-sql-connection': ['password'],
59
+ 'mssql-connection': ['password'],
60
+ 'oracle-connection': ['password'],
61
+ 'data-source-connection': ['password'],
62
+ // SMTP
63
+ 'smtps-connection': ['password'],
64
+ };
65
+ validate(doc, _context) {
66
+ const issues = [];
67
+ const allElements = doc.getElementsByTagName('*');
68
+ for (let i = 0; i < allElements.length; i++) {
69
+ const element = allElements[i];
70
+ const localName = element.localName;
71
+ const sensitiveAttrs = this.findSensitiveAttrs(localName);
72
+ if (!sensitiveAttrs) {
73
+ continue;
74
+ }
75
+ for (const attrName of sensitiveAttrs) {
76
+ const value = element.getAttribute(attrName);
77
+ if (!value || value.trim() === '') {
78
+ continue;
79
+ }
80
+ // Skip DataWeave expressions — they're computed at runtime
81
+ if (value.startsWith('#[')) {
82
+ continue;
83
+ }
84
+ // Must use ${secure::...} — plain ${...} is not sufficient
85
+ if (value.includes('${') && !value.includes('${secure::')) {
86
+ issues.push(this.createIssue(element, `Credential "${attrName}" uses plain property placeholder — must use \${secure::} for encryption`, {
87
+ suggestion: `Replace ${value} with \${secure::${this.extractPropertyName(value)}}`,
88
+ }));
89
+ }
90
+ // Hardcoded value — no placeholder at all
91
+ if (!value.includes('${') && !value.startsWith('#[')) {
92
+ // Ignore booleans and numbers
93
+ if (value === 'true' || value === 'false' || !isNaN(Number(value))) {
94
+ continue;
95
+ }
96
+ issues.push(this.createIssue(element, `Credential "${attrName}" is hardcoded — must use \${secure::} property placeholder`, {
97
+ severity: 'error',
98
+ suggestion: `Use \${secure::${localName}.${attrName}} instead of the hardcoded value`,
99
+ }));
100
+ }
101
+ }
102
+ }
103
+ return issues;
104
+ }
105
+ findSensitiveAttrs(localName) {
106
+ // Exact match first
107
+ if (this.CONNECTOR_SENSITIVE_ATTRS[localName]) {
108
+ return this.CONNECTOR_SENSITIVE_ATTRS[localName];
109
+ }
110
+ // Partial match for compound names
111
+ for (const [key, attrs] of Object.entries(this.CONNECTOR_SENSITIVE_ATTRS)) {
112
+ if (localName.includes(key)) {
113
+ return attrs;
114
+ }
115
+ }
116
+ return undefined;
117
+ }
118
+ extractPropertyName(placeholder) {
119
+ const match = /\$\{([^}]+)\}/.exec(placeholder);
120
+ return match ? match[1] : placeholder;
121
+ }
122
+ }
123
+ exports.ConnectorCredentialsSecuredRule = ConnectorCredentialsSecuredRule;
124
+ //# sourceMappingURL=ConnectorCredentialsSecuredRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConnectorCredentialsSecuredRule.js","sourceRoot":"","sources":["../../../../src/rules/security/ConnectorCredentialsSecuredRule.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,10 @@ import { BaseRule } from '../base/BaseRule';
4
4
  * MULE-201: Hardcoded Credentials
5
5
  *
6
6
  * Passwords and secrets should use secure property placeholders.
7
+ *
8
+ * Enhanced to cover Salesforce connector-specific sensitive attributes
9
+ * (consumerKey, storePassword, tokenId, tokenSecret) and NetSuite
10
+ * OAuth attributes (consumerSecret, tokenKey, tokenSecret).
7
11
  */
8
12
  export declare class HardcodedCredentialsRule extends BaseRule {
9
13
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"HardcodedCredentialsRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/HardcodedCredentialsRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;GAIG;AACH,qBAAa,wBAAyB,SAAQ,QAAQ;IACpD,EAAE,SAAc;IAChB,IAAI,SAA2B;IAC/B,WAAW,SAA+E;IAC1F,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAU9B;IAEF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IA+B7D,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,WAAW;CAoBpB"}
1
+ {"version":3,"file":"HardcodedCredentialsRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/HardcodedCredentialsRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,QAAQ;IACpD,EAAE,SAAc;IAChB,IAAI,SAA2B;IAC/B,WAAW,SAA+E;IAC1F,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAqB9B;IAEF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IA+B7D,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,WAAW;CAoBpB"}
@@ -6,6 +6,10 @@ const BaseRule_1 = require("../base/BaseRule");
6
6
  * MULE-201: Hardcoded Credentials
7
7
  *
8
8
  * Passwords and secrets should use secure property placeholders.
9
+ *
10
+ * Enhanced to cover Salesforce connector-specific sensitive attributes
11
+ * (consumerKey, storePassword, tokenId, tokenSecret) and NetSuite
12
+ * OAuth attributes (consumerSecret, tokenKey, tokenSecret).
9
13
  */
10
14
  class HardcodedCredentialsRule extends BaseRule_1.BaseRule {
11
15
  id = 'MULE-201';
@@ -24,6 +28,17 @@ class HardcodedCredentialsRule extends BaseRule_1.BaseRule {
24
28
  'token',
25
29
  'accessToken',
26
30
  'privateKey',
31
+ // Salesforce connector attrs
32
+ 'consumerKey',
33
+ 'consumerSecret',
34
+ 'storePassword',
35
+ 'tokenId',
36
+ 'tokenSecret',
37
+ // NetSuite OAuth attrs
38
+ 'tokenKey',
39
+ // Keystore/truststore
40
+ 'keyPassword',
41
+ 'keystorePassword',
27
42
  ];
28
43
  validate(doc, _context) {
29
44
  const issues = [];
@@ -1 +1 @@
1
- {"version":3,"file":"HardcodedCredentialsRule.js","sourceRoot":"","sources":["../../../../src/rules/security/HardcodedCredentialsRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;GAIG;AACH,MAAa,wBAAyB,SAAQ,mBAAQ;IACpD,EAAE,GAAG,UAAU,CAAC;IAChB,IAAI,GAAG,uBAAuB,CAAC;IAC/B,WAAW,GAAG,2EAA2E,CAAC;IAC1F,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,eAAe,GAAG;QACjC,UAAU;QACV,QAAQ;QACR,cAAc;QACd,eAAe;QACf,QAAQ;QACR,SAAS;QACT,OAAO;QACP,aAAa;QACb,YAAY;KACb,CAAC;IAEF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBAEzB,yCAAyC;gBACzC,IAAI,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,OAAO,EACP,aAAa,IAAI,CAAC,IAAI,0CAA0C,EAChE;wBACE,UAAU,EAAE,kBAAkB,IAAI,CAAC,IAAI,8BAA8B;qBACtE,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,oBAAoB,CAAC,QAAgB;QAC3C,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAEO,WAAW,CAAC,KAAa;QAC/B,iCAAiC;QACjC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,sEAAsE;QACtE,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,+DAA+D;QAC/D,yDAAyD;QACzD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4DAA4D;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA3ED,4DA2EC"}
1
+ {"version":3,"file":"HardcodedCredentialsRule.js","sourceRoot":"","sources":["../../../../src/rules/security/HardcodedCredentialsRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;GAQG;AACH,MAAa,wBAAyB,SAAQ,mBAAQ;IACpD,EAAE,GAAG,UAAU,CAAC;IAChB,IAAI,GAAG,uBAAuB,CAAC;IAC/B,WAAW,GAAG,2EAA2E,CAAC;IAC1F,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,eAAe,GAAG;QACjC,UAAU;QACV,QAAQ;QACR,cAAc;QACd,eAAe;QACf,QAAQ;QACR,SAAS;QACT,OAAO;QACP,aAAa;QACb,YAAY;QACZ,6BAA6B;QAC7B,aAAa;QACb,gBAAgB;QAChB,eAAe;QACf,SAAS;QACT,aAAa;QACb,uBAAuB;QACvB,UAAU;QACV,sBAAsB;QACtB,aAAa;QACb,kBAAkB;KACnB,CAAC;IAEF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBAEzB,yCAAyC;gBACzC,IAAI,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,OAAO,EACP,aAAa,IAAI,CAAC,IAAI,0CAA0C,EAChE;wBACE,UAAU,EAAE,kBAAkB,IAAI,CAAC,IAAI,8BAA8B;qBACtE,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,oBAAoB,CAAC,QAAgB;QAC3C,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAEO,WAAW,CAAC,KAAa;QAC/B,iCAAiC;QACjC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,sEAAsE;QACtE,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,+DAA+D;QAC/D,yDAAyD;QACzD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4DAA4D;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAtFD,4DAsFC"}
@@ -0,0 +1,25 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * SEC-010: Secure Properties Encryption Algorithm
5
+ *
6
+ * When `<secure-properties:config>` specifies an encryption algorithm, it
7
+ * should use a strong algorithm (AES, Blowfish) and not a weak or
8
+ * deprecated one (DES, RC2, RC4).
9
+ *
10
+ * Also validates that when secure properties are used, the `encrypt`
11
+ * element exists (i.e., properties are actually encrypted, not just
12
+ * marked as "secure" with no encryption).
13
+ */
14
+ export declare class SecurePropertiesEncryptionRule extends BaseRule {
15
+ id: string;
16
+ name: string;
17
+ description: string;
18
+ severity: "warning";
19
+ category: "security";
20
+ issueType: IssueType;
21
+ private readonly WEAK_ALGORITHMS;
22
+ private readonly STRONG_ALGORITHMS;
23
+ validate(doc: Document, _context: ValidationContext): Issue[];
24
+ }
25
+ //# sourceMappingURL=SecurePropertiesEncryptionRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurePropertiesEncryptionRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesEncryptionRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,qBAAa,8BAA+B,SAAQ,QAAQ;IAC1D,EAAE,SAAa;IACf,IAAI,SAAkC;IACtC,WAAW,SAA6D;IACxE,QAAQ,EAAG,SAAS,CAAU;IAC9B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IACnE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuB;IAEzD,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAsD9D"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecurePropertiesEncryptionRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * SEC-010: Secure Properties Encryption Algorithm
7
+ *
8
+ * When `<secure-properties:config>` specifies an encryption algorithm, it
9
+ * should use a strong algorithm (AES, Blowfish) and not a weak or
10
+ * deprecated one (DES, RC2, RC4).
11
+ *
12
+ * Also validates that when secure properties are used, the `encrypt`
13
+ * element exists (i.e., properties are actually encrypted, not just
14
+ * marked as "secure" with no encryption).
15
+ */
16
+ class SecurePropertiesEncryptionRule extends BaseRule_1.BaseRule {
17
+ id = 'SEC-010';
18
+ name = 'Secure Properties Encryption';
19
+ description = 'Secure properties must use strong encryption algorithms';
20
+ severity = 'warning';
21
+ category = 'security';
22
+ issueType = 'vulnerability';
23
+ WEAK_ALGORITHMS = ['DES', 'DESede', 'RC2', 'RC4'];
24
+ STRONG_ALGORITHMS = ['AES', 'Blowfish'];
25
+ validate(doc, _context) {
26
+ const issues = [];
27
+ // Match secure-properties:config or secure-configuration-properties
28
+ const secureConfigs = this.select('//*[local-name()="config" and contains(namespace-uri(), "secure-properties")] | ' +
29
+ '//*[local-name()="secure-configuration-properties"]', doc);
30
+ for (const config of secureConfigs) {
31
+ // Check for encrypt element presence
32
+ const encryptElements = this.select('.//*[local-name()="encrypt"]', config);
33
+ if (encryptElements.length === 0) {
34
+ const docName = this.getDocName(config) ?? 'Secure Properties Config';
35
+ issues.push(this.createIssue(config, `"${docName}" has no <encrypt> element — properties may not be encrypted`, {
36
+ severity: 'warning',
37
+ suggestion: 'Add <secure-properties:encrypt algorithm="AES" mode="CBC"/> to enable encryption',
38
+ }));
39
+ continue;
40
+ }
41
+ // Check encryption algorithm
42
+ for (const encrypt of encryptElements) {
43
+ const algorithm = this.getAttribute(encrypt, 'algorithm');
44
+ if (!algorithm) {
45
+ continue;
46
+ }
47
+ if (this.WEAK_ALGORITHMS.includes(algorithm)) {
48
+ issues.push(this.createIssue(encrypt, `Weak encryption algorithm "${algorithm}" — use ${this.STRONG_ALGORITHMS.join(' or ')} instead`, {
49
+ severity: 'error',
50
+ suggestion: `Replace algorithm="${algorithm}" with algorithm="AES"`,
51
+ }));
52
+ }
53
+ }
54
+ }
55
+ return issues;
56
+ }
57
+ }
58
+ exports.SecurePropertiesEncryptionRule = SecurePropertiesEncryptionRule;
59
+ //# sourceMappingURL=SecurePropertiesEncryptionRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurePropertiesEncryptionRule.js","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesEncryptionRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,8BAA+B,SAAQ,mBAAQ;IAC1D,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,8BAA8B,CAAC;IACtC,WAAW,GAAG,yDAAyD,CAAC;IACxE,QAAQ,GAAG,SAAkB,CAAC;IAC9B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,eAAe,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAClD,iBAAiB,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAEzD,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,oEAAoE;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAC/B,kFAAkF;YAChF,qDAAqD,EACvD,GAAG,CACJ,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,qCAAqC;YACrC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,8BAA8B,EAAE,MAAkB,CAAC,CAAC;YAExF,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,0BAA0B,CAAC;gBACtE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,MAAM,EACN,IAAI,OAAO,8DAA8D,EACzE;oBACE,QAAQ,EAAE,SAAS;oBACnB,UAAU,EACR,kFAAkF;iBACrF,CACF,CACF,CAAC;gBACF,SAAS;YACX,CAAC;YAED,6BAA6B;YAC7B,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;gBACtC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAC1D,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,SAAS;gBACX,CAAC;gBAED,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,OAAO,EACP,8BAA8B,SAAS,WAAW,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAC/F;wBACE,QAAQ,EAAE,OAAO;wBACjB,UAAU,EAAE,sBAAsB,SAAS,wBAAwB;qBACpE,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAjED,wEAiEC"}
@@ -0,0 +1,23 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * SEC-008: Secure Properties Key Configuration
5
+ *
6
+ * The `<secure-properties:config>` element's `key` attribute must use a
7
+ * property placeholder (`${...}`) — never a hardcoded encryption key.
8
+ *
9
+ * A hardcoded key in the XML defeats the purpose of encryption because
10
+ * anyone with access to the source code can decrypt all secure properties.
11
+ * The key should be injected via a system property or environment variable
12
+ * at deployment time (e.g., `-Dsecure.key=...` in the Mule runtime args).
13
+ */
14
+ export declare class SecurePropertiesKeyRule extends BaseRule {
15
+ id: string;
16
+ name: string;
17
+ description: string;
18
+ severity: "error";
19
+ category: "security";
20
+ issueType: IssueType;
21
+ validate(doc: Document, _context: ValidationContext): Issue[];
22
+ }
23
+ //# sourceMappingURL=SecurePropertiesKeyRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurePropertiesKeyRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesKeyRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,EAAE,SAAa;IACf,IAAI,SAA2B;IAC/B,WAAW,SAA4D;IACvE,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAkC9D"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecurePropertiesKeyRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * SEC-008: Secure Properties Key Configuration
7
+ *
8
+ * The `<secure-properties:config>` element's `key` attribute must use a
9
+ * property placeholder (`${...}`) — never a hardcoded encryption key.
10
+ *
11
+ * A hardcoded key in the XML defeats the purpose of encryption because
12
+ * anyone with access to the source code can decrypt all secure properties.
13
+ * The key should be injected via a system property or environment variable
14
+ * at deployment time (e.g., `-Dsecure.key=...` in the Mule runtime args).
15
+ */
16
+ class SecurePropertiesKeyRule extends BaseRule_1.BaseRule {
17
+ id = 'SEC-008';
18
+ name = 'Secure Properties Key';
19
+ description = 'Secure properties encryption key must not be hardcoded';
20
+ severity = 'error';
21
+ category = 'security';
22
+ issueType = 'vulnerability';
23
+ validate(doc, _context) {
24
+ const issues = [];
25
+ // Match secure-properties:config or secure-configuration-properties
26
+ const secureConfigs = this.select('//*[local-name()="config" and contains(namespace-uri(), "secure-properties")] | ' +
27
+ '//*[local-name()="secure-configuration-properties"]', doc);
28
+ for (const config of secureConfigs) {
29
+ const key = this.getAttribute(config, 'key');
30
+ if (!key) {
31
+ continue;
32
+ }
33
+ // Key must be a property placeholder
34
+ if (!key.includes('${')) {
35
+ const docName = this.getDocName(config) ?? 'Secure Properties Config';
36
+ issues.push(this.createIssue(config, `"${docName}" has hardcoded encryption key — defeats the purpose of property encryption`, {
37
+ suggestion: 'Use a property placeholder: key="${secure.key}" and inject via -Dsecure.key=... at runtime',
38
+ }));
39
+ }
40
+ }
41
+ return issues;
42
+ }
43
+ }
44
+ exports.SecurePropertiesKeyRule = SecurePropertiesKeyRule;
45
+ //# sourceMappingURL=SecurePropertiesKeyRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecurePropertiesKeyRule.js","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesKeyRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,uBAAwB,SAAQ,mBAAQ;IACnD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,uBAAuB,CAAC;IAC/B,WAAW,GAAG,wDAAwD,CAAC;IACvE,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEvC,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,oEAAoE;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAC/B,kFAAkF;YAChF,qDAAqD,EACvD,GAAG,CACJ,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,SAAS;YACX,CAAC;YAED,qCAAqC;YACrC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,0BAA0B,CAAC;gBACtE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,MAAM,EACN,IAAI,OAAO,6EAA6E,EACxF;oBACE,UAAU,EACR,4FAA4F;iBAC/F,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA1CD,0DA0CC"}
@@ -0,0 +1,25 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * SEC-009: TLS Keystore/Truststore Passwords Secured
5
+ *
6
+ * TLS context keystore and truststore passwords must use secure property
7
+ * placeholders (`${secure::...}`) rather than plain-text placeholders or
8
+ * hardcoded values.
9
+ *
10
+ * These passwords protect the private keys and certificates used for
11
+ * mutual TLS (mTLS) authentication. Leaking them enables impersonation
12
+ * attacks and man-in-the-middle interception.
13
+ */
14
+ export declare class TlsKeystorePasswordRule extends BaseRule {
15
+ id: string;
16
+ name: string;
17
+ description: string;
18
+ severity: "error";
19
+ category: "security";
20
+ issueType: IssueType;
21
+ private readonly PASSWORD_ATTRS;
22
+ validate(doc: Document, _context: ValidationContext): Issue[];
23
+ private extractPropName;
24
+ }
25
+ //# sourceMappingURL=TlsKeystorePasswordRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TlsKeystorePasswordRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/TlsKeystorePasswordRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,EAAE,SAAa;IACf,IAAI,SAAmC;IACvC,WAAW,SAAyE;IACpF,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAE9D,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IAoD7D,OAAO,CAAC,eAAe;CAIxB"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TlsKeystorePasswordRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * SEC-009: TLS Keystore/Truststore Passwords Secured
7
+ *
8
+ * TLS context keystore and truststore passwords must use secure property
9
+ * placeholders (`${secure::...}`) rather than plain-text placeholders or
10
+ * hardcoded values.
11
+ *
12
+ * These passwords protect the private keys and certificates used for
13
+ * mutual TLS (mTLS) authentication. Leaking them enables impersonation
14
+ * attacks and man-in-the-middle interception.
15
+ */
16
+ class TlsKeystorePasswordRule extends BaseRule_1.BaseRule {
17
+ id = 'SEC-009';
18
+ name = 'TLS Keystore Password Secured';
19
+ description = 'TLS keystore/truststore passwords must use ${secure::} placeholders';
20
+ severity = 'error';
21
+ category = 'security';
22
+ issueType = 'vulnerability';
23
+ PASSWORD_ATTRS = ['password', 'keyPassword'];
24
+ validate(doc, _context) {
25
+ const issues = [];
26
+ // Select all key-store and trust-store elements
27
+ const stores = this.select('//*[local-name()="key-store" or local-name()="trust-store"]', doc);
28
+ for (const store of stores) {
29
+ for (const attrName of this.PASSWORD_ATTRS) {
30
+ const value = this.getAttribute(store, attrName);
31
+ if (!value || value.trim() === '') {
32
+ continue;
33
+ }
34
+ // DataWeave expressions are OK
35
+ if (value.startsWith('#[')) {
36
+ continue;
37
+ }
38
+ // Must use ${secure::...}
39
+ if (value.includes('${') && !value.includes('${secure::')) {
40
+ const storeName = store.localName;
41
+ issues.push(this.createIssue(store, `TLS ${storeName} "${attrName}" uses plain property placeholder — must use \${secure::}`, {
42
+ suggestion: `Replace ${value} with \${secure::${this.extractPropName(value)}}`,
43
+ }));
44
+ }
45
+ // Hardcoded value
46
+ if (!value.includes('${') && !value.startsWith('#[')) {
47
+ const storeName = store.localName;
48
+ issues.push(this.createIssue(store, `TLS ${storeName} "${attrName}" is hardcoded — must use \${secure::} placeholder`, {
49
+ severity: 'error',
50
+ suggestion: `Use \${secure::tls.${storeName}.${attrName}} instead of the hardcoded value`,
51
+ }));
52
+ }
53
+ }
54
+ }
55
+ return issues;
56
+ }
57
+ extractPropName(placeholder) {
58
+ const match = /\$\{([^}]+)\}/.exec(placeholder);
59
+ return match ? match[1] : placeholder;
60
+ }
61
+ }
62
+ exports.TlsKeystorePasswordRule = TlsKeystorePasswordRule;
63
+ //# sourceMappingURL=TlsKeystorePasswordRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TlsKeystorePasswordRule.js","sourceRoot":"","sources":["../../../../src/rules/security/TlsKeystorePasswordRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,uBAAwB,SAAQ,mBAAQ;IACnD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,+BAA+B,CAAC;IACvC,WAAW,GAAG,qEAAqE,CAAC;IACpF,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,cAAc,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAE9D,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,gDAAgD;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,6DAA6D,EAAE,GAAG,CAAC,CAAC;QAE/F,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACjD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;oBAClC,SAAS;gBACX,CAAC;gBAED,+BAA+B;gBAC/B,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBAED,0BAA0B;gBAC1B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC1D,MAAM,SAAS,GAAI,KAAiB,CAAC,SAAS,CAAC;oBAC/C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,KAAK,EACL,OAAO,SAAS,KAAK,QAAQ,2DAA2D,EACxF;wBACE,UAAU,EAAE,WAAW,KAAK,oBAAoB,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG;qBAC/E,CACF,CACF,CAAC;gBACJ,CAAC;gBAED,kBAAkB;gBAClB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrD,MAAM,SAAS,GAAI,KAAiB,CAAC,SAAS,CAAC;oBAC/C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,KAAK,EACL,OAAO,SAAS,KAAK,QAAQ,oDAAoD,EACjF;wBACE,QAAQ,EAAE,OAAO;wBACjB,UAAU,EAAE,sBAAsB,SAAS,IAAI,QAAQ,kCAAkC;qBAC1F,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,eAAe,CAAC,WAAmB;QACzC,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IACxC,CAAC;CACF;AAlED,0DAkEC"}
@@ -0,0 +1,26 @@
1
+ import { ValidationContext, Issue, IssueType } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * STD-001: APIKit Route Variable Consistency
5
+ *
6
+ * In APIKit projects, implementation flows (get:\resource:config, etc.)
7
+ * should follow a consistent pattern for setting response variables.
8
+ * For example, if some flows set httpStatus but others don't, this
9
+ * inconsistency can lead to unexpected HTTP responses.
10
+ *
11
+ * This rule flags APIKit implementation flows that deviate from the
12
+ * most common pattern in the file (e.g., if 4/5 flows set httpStatus
13
+ * but one doesn't, the outlier is flagged).
14
+ */
15
+ export declare class ApikitRouteVariableConsistencyRule extends BaseRule {
16
+ id: string;
17
+ name: string;
18
+ description: string;
19
+ severity: "info";
20
+ category: "standards";
21
+ issueType: IssueType;
22
+ /** Pattern for APIKit-generated flow names */
23
+ private readonly APIKIT_FLOW_PATTERN;
24
+ validate(doc: Document, _context: ValidationContext): Issue[];
25
+ }
26
+ //# sourceMappingURL=ApikitRouteVariableConsistencyRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitRouteVariableConsistencyRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/standards/ApikitRouteVariableConsistencyRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,qBAAa,kCAAmC,SAAQ,QAAQ;IAC9D,EAAE,SAAa;IACf,IAAI,SAAuC;IAC3C,WAAW,SAC8E;IACzF,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,WAAW,CAAU;IAChC,SAAS,EAAE,SAAS,CAAgB;IAEpC,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkD;IAEtF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAoD9D"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApikitRouteVariableConsistencyRule = void 0;
4
+ const BaseRule_1 = require("../base/BaseRule");
5
+ /**
6
+ * STD-001: APIKit Route Variable Consistency
7
+ *
8
+ * In APIKit projects, implementation flows (get:\resource:config, etc.)
9
+ * should follow a consistent pattern for setting response variables.
10
+ * For example, if some flows set httpStatus but others don't, this
11
+ * inconsistency can lead to unexpected HTTP responses.
12
+ *
13
+ * This rule flags APIKit implementation flows that deviate from the
14
+ * most common pattern in the file (e.g., if 4/5 flows set httpStatus
15
+ * but one doesn't, the outlier is flagged).
16
+ */
17
+ class ApikitRouteVariableConsistencyRule extends BaseRule_1.BaseRule {
18
+ id = 'STD-001';
19
+ name = 'APIKit Route Variable Consistency';
20
+ description = 'APIKit implementation flows should follow consistent patterns for response variables';
21
+ severity = 'info';
22
+ category = 'standards';
23
+ issueType = 'code-smell';
24
+ /** Pattern for APIKit-generated flow names */
25
+ APIKIT_FLOW_PATTERN = /^(get|post|put|patch|delete|head|options):\\/;
26
+ validate(doc, _context) {
27
+ const issues = [];
28
+ const flows = this.select('//mule:flow', doc);
29
+ // Collect APIKit implementation flows
30
+ const apikitFlows = [];
31
+ for (const flow of flows) {
32
+ const flowName = this.getAttribute(flow, 'name') ?? '';
33
+ if (!this.APIKIT_FLOW_PATTERN.test(flowName)) {
34
+ continue;
35
+ }
36
+ const setsHttpStatus = this.exists('.//*[local-name()="set-variable" and @variableName="httpStatus"]', flow);
37
+ apikitFlows.push({ name: flowName, node: flow, setsHttpStatus });
38
+ }
39
+ // Need at least 3 flows to detect a meaningful pattern
40
+ if (apikitFlows.length < 3) {
41
+ return issues;
42
+ }
43
+ // Determine the majority pattern
44
+ const withStatus = apikitFlows.filter((f) => f.setsHttpStatus).length;
45
+ const withoutStatus = apikitFlows.length - withStatus;
46
+ // Only flag if there's a clear majority (>60%) and at least one outlier
47
+ if (withStatus > withoutStatus && withoutStatus > 0 && withStatus / apikitFlows.length > 0.6) {
48
+ // Majority sets httpStatus — flag those that don't
49
+ for (const flow of apikitFlows) {
50
+ if (!flow.setsHttpStatus) {
51
+ issues.push(this.createIssue(flow.node, `APIKit flow "${flow.name}" does not set httpStatus, but ${withStatus}/${apikitFlows.length} other flows do`, {
52
+ suggestion: 'Add a set-variable for httpStatus to maintain consistency across all APIKit implementation flows',
53
+ }));
54
+ }
55
+ }
56
+ }
57
+ return issues;
58
+ }
59
+ }
60
+ exports.ApikitRouteVariableConsistencyRule = ApikitRouteVariableConsistencyRule;
61
+ //# sourceMappingURL=ApikitRouteVariableConsistencyRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApikitRouteVariableConsistencyRule.js","sourceRoot":"","sources":["../../../../src/rules/standards/ApikitRouteVariableConsistencyRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;;GAWG;AACH,MAAa,kCAAmC,SAAQ,mBAAQ;IAC9D,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,mCAAmC,CAAC;IAC3C,WAAW,GACT,sFAAsF,CAAC;IACzF,QAAQ,GAAG,MAAe,CAAC;IAC3B,QAAQ,GAAG,WAAoB,CAAC;IAChC,SAAS,GAAc,YAAY,CAAC;IAEpC,8CAA8C;IAC7B,mBAAmB,GAAG,8CAA8C,CAAC;IAEtF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAE9C,sCAAsC;QACtC,MAAM,WAAW,GAAiE,EAAE,CAAC;QAErF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAChC,kEAAkE,EAClE,IAAI,CACL,CAAC;YAEF,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,uDAAuD;QACvD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,iCAAiC;QACjC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;QACtE,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;QAEtD,wEAAwE;QACxE,IAAI,UAAU,GAAG,aAAa,IAAI,aAAa,GAAG,CAAC,IAAI,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC7F,mDAAmD;YACnD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;gBAC/B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBACzB,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,IAAI,CAAC,IAAI,EACT,gBAAgB,IAAI,CAAC,IAAI,kCAAkC,UAAU,IAAI,WAAW,CAAC,MAAM,iBAAiB,EAC5G;wBACE,UAAU,EACR,kGAAkG;qBACrG,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAhED,gFAgEC"}
@@ -0,0 +1,34 @@
1
+ import { ValidationContext, Issue } from '../../types';
2
+ import { BaseRule } from '../base/BaseRule';
3
+ /**
4
+ * CFG-001: Configuration Properties Ordering
5
+ *
6
+ * Mule configuration-properties elements should be loaded in the correct
7
+ * order: global defaults first, then environment-specific overrides, then
8
+ * secure properties. This ensures predictable property resolution (Mule
9
+ * uses last-wins for overlapping keys).
10
+ *
11
+ * Expected ordering pattern:
12
+ * 1. config/global.yaml (or common.yaml, defaults.yaml)
13
+ * 2. config/${mule.env}.yaml (environment-specific)
14
+ * 3. secure-properties:config (encrypted secrets)
15
+ * 4. entity-config/*.yaml (optional, additive)
16
+ *
17
+ * This rule flags when env-specific properties appear before global
18
+ * defaults, which would cause globals to override env-specific values.
19
+ */
20
+ export declare class ConfigPropertiesOrderingRule extends BaseRule {
21
+ id: string;
22
+ name: string;
23
+ description: string;
24
+ severity: "info";
25
+ category: "standards";
26
+ /** Patterns that identify global/default property files */
27
+ private readonly GLOBAL_PATTERNS;
28
+ /** Patterns that identify env-specific property files */
29
+ private readonly ENV_PATTERNS;
30
+ validate(doc: Document, _context: ValidationContext): Issue[];
31
+ private isGlobalFile;
32
+ private isEnvSpecificFile;
33
+ }
34
+ //# sourceMappingURL=ConfigPropertiesOrderingRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigPropertiesOrderingRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/standards/ConfigPropertiesOrderingRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,4BAA6B,SAAQ,QAAQ;IACxD,EAAE,SAAa;IACf,IAAI,SAAuC;IAC3C,WAAW,SACwF;IACnG,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,WAAW,CAAU;IAEhC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAO9B;IAEF,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoD;IAEjF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IA6C7D,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,iBAAiB;CAG1B"}