0xray 4.0.36 → 4.0.37

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 (169) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.xray/features.json +1 -1
  3. package/dist/CHANGELOG.md +15 -0
  4. package/dist/analytics/emerging-pattern-detector.d.ts +12 -1
  5. package/dist/analytics/emerging-pattern-detector.js +37 -12
  6. package/dist/analytics/pattern-learning-engine.js +1 -9
  7. package/dist/analytics/predictive-analytics.js +51 -33
  8. package/dist/analytics/prompt-pattern-analyzer.d.ts +1 -0
  9. package/dist/analytics/prompt-pattern-analyzer.js +39 -20
  10. package/dist/analytics/routing-performance-analyzer.d.ts +2 -0
  11. package/dist/analytics/routing-performance-analyzer.js +89 -37
  12. package/dist/analytics/simple-pattern-analyzer.d.ts +4 -0
  13. package/dist/analytics/simple-pattern-analyzer.js +66 -28
  14. package/dist/architect/architect-tools.d.ts +3 -0
  15. package/dist/architect/architect-tools.js +22 -0
  16. package/dist/cli/commands/grok-install.js +1 -1
  17. package/dist/cli/commands/hermes-install.js +11 -5
  18. package/dist/cli/commands/openclaw-install.js +13 -7
  19. package/dist/cli/commands/opencode-install.js +7 -4
  20. package/dist/cli/commands/suit-monitor.d.ts +30 -0
  21. package/dist/cli/commands/suit-monitor.js +128 -0
  22. package/dist/cli/index.js +52 -15
  23. package/dist/cli/suit-pulse.d.ts +29 -0
  24. package/dist/cli/suit-pulse.js +270 -0
  25. package/dist/delegation/agent-delegator.d.ts +4 -2
  26. package/dist/delegation/agent-delegator.js +46 -27
  27. package/dist/delegation/agent-expertise.js +2 -1
  28. package/dist/delegation/analytics/outcome-tracker.d.ts +6 -0
  29. package/dist/delegation/analytics/outcome-tracker.js +17 -3
  30. package/dist/delegation/ast-code-parser.d.ts +5 -0
  31. package/dist/delegation/ast-code-parser.js +53 -48
  32. package/dist/delegation/codebase-context-analyzer.d.ts +3 -7
  33. package/dist/delegation/codebase-context-analyzer.js +188 -159
  34. package/dist/delegation/session-coordinator.js +3 -2
  35. package/dist/enforcement/loaders/codex-loader.js +18 -14
  36. package/dist/enforcement/validators/architecture-validators.js +115 -9
  37. package/dist/governance/codex-policy.service.d.ts +12 -2
  38. package/dist/governance/codex-policy.service.js +91 -16
  39. package/dist/integrations/grok/hooks/session-start.js +6 -6
  40. package/dist/integrations/hooks/goggles-pipeline.mjs +169 -28
  41. package/dist/integrations/hooks/goggles-planes.json +172 -8
  42. package/dist/integrations/hooks/plates.cjs +138 -0
  43. package/dist/integrations/hooks/station-hook-runtime.cjs +63 -5
  44. package/dist/integrations/hooks/write-home.cjs +59 -0
  45. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  46. package/dist/mcps/architect-tools.server.d.ts +6 -0
  47. package/dist/mcps/architect-tools.server.js +19 -18
  48. package/dist/mcps/orchestrator/server.d.ts +4 -3
  49. package/dist/mcps/orchestrator/server.js +29 -17
  50. package/dist/memory-routing/lookup-cache.d.ts +8 -0
  51. package/dist/memory-routing/lookup-cache.js +72 -0
  52. package/dist/memory-routing/plates.d.ts +1 -1
  53. package/dist/memory-routing/plates.js +26 -0
  54. package/dist/memory-routing/provider-loader.js +3 -0
  55. package/dist/metrics/agent-metrics.d.ts +14 -5
  56. package/dist/metrics/agent-metrics.js +362 -224
  57. package/dist/nucleus/synthesis-consult-receipt.js +38 -16
  58. package/dist/orchestrator/enhanced-multi-agent-orchestrator.d.ts +5 -0
  59. package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +9 -0
  60. package/dist/orchestrator/multi-agent-orchestration-coordinator.js +1 -2
  61. package/dist/orchestrator/orchestrator.js +1 -2
  62. package/dist/processors/implementations/agents-md-validation-processor.d.ts +0 -1
  63. package/dist/processors/implementations/agents-md-validation-processor.js +0 -11
  64. package/dist/processors/implementations/console-log-guard-processor.js +39 -50
  65. package/dist/processors/implementations/performance-budget-processor.d.ts +0 -5
  66. package/dist/processors/implementations/performance-budget-processor.js +29 -38
  67. package/dist/processors/implementations/storytelling-trigger-processor.d.ts +5 -0
  68. package/dist/processors/implementations/storytelling-trigger-processor.js +69 -16
  69. package/dist/processors/implementations/test-auto-creation-processor.js +39 -36
  70. package/dist/reporting/framework-reporting-system.d.ts +3 -0
  71. package/dist/reporting/framework-reporting-system.js +61 -8
  72. package/dist/reporting/log-parser.js +188 -105
  73. package/dist/reporting/metrics.js +42 -18
  74. package/dist/security/prompt-security-validator.js +8 -7
  75. package/dist/security/security-auditor.d.ts +4 -0
  76. package/dist/security/security-auditor.js +132 -57
  77. package/dist/security/security-hardener.d.ts +2 -0
  78. package/dist/security/security-hardener.js +31 -6
  79. package/dist/security/security-headers.d.ts +2 -0
  80. package/dist/security/security-headers.js +23 -21
  81. package/dist/security/security-scanner.js +18 -4
  82. package/dist/session/session-cleanup-manager.d.ts +2 -0
  83. package/dist/session/session-cleanup-manager.js +29 -8
  84. package/dist/session/session-monitor.d.ts +14 -4
  85. package/dist/session/session-monitor.js +208 -106
  86. package/dist/session/session-state-manager.d.ts +11 -0
  87. package/dist/session/session-state-manager.js +90 -8
  88. package/docs-site/docs/plates/activity-log.md +38 -0
  89. package/docs-site/docs/plates/cursor-compact.md +35 -0
  90. package/docs-site/docs/plates/grok-compact.md +35 -0
  91. package/docs-site/docs/plates/index.md +25 -3
  92. package/docs-site/docs/plates/inference-files.md +35 -0
  93. package/docs-site/docs/plates/kept-line.md +35 -0
  94. package/docs-site/docs/plates/lens-gate.md +35 -0
  95. package/docs-site/docs/plates/lens-page.md +35 -0
  96. package/docs-site/docs/plates/notes-page.md +35 -0
  97. package/docs-site/docs/plates/package-face.md +35 -0
  98. package/docs-site/docs/plates/payload-heat.md +35 -0
  99. package/docs-site/docs/plates/pickup-stamp.md +35 -0
  100. package/docs-site/docs/plates/pre-tool.md +35 -0
  101. package/docs-site/docs/plates/record-map.md +41 -0
  102. package/docs-site/docs/plates/reflection-page.md +35 -0
  103. package/docs-site/docs/plates/review.md +57 -0
  104. package/docs-site/docs/plates/session-capture.md +38 -0
  105. package/docs-site/docs/plates/site-manual.md +35 -0
  106. package/docs-site/docs/plates/stamp-plate.md +35 -0
  107. package/docs-site/docs/plates/station-card.md +35 -0
  108. package/docs-site/docs/plates/station-heat.md +35 -0
  109. package/docs-site/docs/plates/suit-organs.md +38 -0
  110. package/docs-site/docs/plates/suit-settings.md +35 -0
  111. package/docs-site/docs/plates/suit-wear.md +37 -0
  112. package/docs-site/docs/plates/trail-state.md +35 -0
  113. package/docs-site/docs/plates/work-fresh.md +35 -0
  114. package/docs-site/docs/plates/write-home.md +38 -0
  115. package/package.json +3 -2
  116. package/scripts/node/install-bridges.cjs +302 -78
  117. package/scripts/node/postinstall.cjs +14 -3
  118. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  119. package/src/mcps/architect-tools.server.ts +25 -20
  120. package/src/mcps/orchestrator/server.ts +33 -19
  121. package/xray/features.json +1 -1
  122. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +0 -1
  123. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +0 -1
  124. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +0 -1
  125. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +0 -1
  126. package/vendor/@0xray/repertoire/dist/index.d.ts.map +0 -1
  127. package/vendor/@0xray/repertoire/dist/index.js.map +0 -1
  128. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +0 -1
  129. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +0 -1
  130. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +0 -1
  131. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +0 -1
  132. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +0 -1
  133. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +0 -1
  134. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +0 -1
  135. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +0 -1
  136. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +0 -1
  137. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +0 -1
  138. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +0 -1
  139. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +0 -1
  140. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +0 -1
  141. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +0 -1
  142. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +0 -1
  143. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +0 -1
  144. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +0 -1
  145. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +0 -1
  146. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +0 -1
  147. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +0 -1
  148. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +0 -1
  149. package/vendor/@0xray/repertoire/dist/paths.js.map +0 -1
  150. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +0 -1
  151. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +0 -1
  152. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +0 -1
  153. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +0 -1
  154. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +0 -1
  155. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +0 -1
  156. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts.map +0 -1
  157. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js.map +0 -1
  158. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +0 -1
  159. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +0 -1
  160. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +0 -1
  161. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +0 -1
  162. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +0 -1
  163. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +0 -1
  164. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +0 -1
  165. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +0 -1
  166. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +0 -1
  167. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +0 -1
  168. package/vendor/@0xray/repertoire/dist/types.d.ts.map +0 -1
  169. package/vendor/@0xray/repertoire/dist/types.js.map +0 -1
@@ -30,11 +30,15 @@ export interface SecurityAuditResult {
30
30
  export declare class SecurityAuditor {
31
31
  private readonly dangerousPatterns;
32
32
  private readonly dangerousImports;
33
+ private readonly compiledImports;
34
+ private textCache;
33
35
  /**
34
36
  * Run comprehensive security audit
35
37
  */
36
38
  auditProject(projectPath?: string): Promise<SecurityAuditResult>;
37
39
  private getAllFiles;
40
+ private visitNamed;
41
+ private readText;
38
42
  private shouldSkipDirectory;
39
43
  private shouldAuditFile;
40
44
  private auditFile;
@@ -9,6 +9,20 @@
9
9
  import { readFileSync, readdirSync, statSync } from "fs";
10
10
  import { join } from "path";
11
11
  import { frameworkLogger } from "../core/framework-logger.js";
12
+ const RECOMMENDATIONS = {
13
+ "code-injection": "Use static code analysis and avoid dynamic code execution",
14
+ "command-injection": "Validate and sanitize all user inputs, use parameterized commands",
15
+ "sql-injection": "Use parameterized queries or ORM with built-in protection",
16
+ "path-traversal": "Validate paths, use allowlists, resolve to absolute paths",
17
+ "hardcoded-secrets": "Use environment variables or secure credential management",
18
+ "weak-cryptography": "Use cryptographically secure random number generators",
19
+ "information-disclosure": "Avoid logging sensitive information, use proper log levels",
20
+ "input-validation": "Implement comprehensive input validation and sanitization",
21
+ deserialization: "Validate serialized data, use safe deserialization libraries",
22
+ "race-conditions": "Use proper synchronization primitives",
23
+ "dangerous-imports": "Review usage and implement proper access controls",
24
+ "file-permissions": "Restrict file permissions to minimum required access",
25
+ };
12
26
  export class SecurityAuditor {
13
27
  dangerousPatterns = [
14
28
  // Code injection
@@ -17,18 +31,21 @@ export class SecurityAuditor {
17
31
  severity: "critical",
18
32
  category: "code-injection",
19
33
  cwe: "CWE-95",
34
+ hints: ["eval"],
20
35
  },
21
36
  {
22
37
  pattern: /Function\s*\(/g,
23
38
  severity: "critical",
24
39
  category: "code-injection",
25
40
  cwe: "CWE-95",
41
+ hints: ["Function"],
26
42
  },
27
43
  {
28
44
  pattern: /new\s+Function\s*\(/g,
29
45
  severity: "critical",
30
46
  category: "code-injection",
31
47
  cwe: "CWE-95",
48
+ hints: ["Function"],
32
49
  },
33
50
  // Command injection
34
51
  {
@@ -36,18 +53,21 @@ export class SecurityAuditor {
36
53
  severity: "high",
37
54
  category: "command-injection",
38
55
  cwe: "CWE-78",
56
+ hints: ["child_process"],
39
57
  },
40
58
  {
41
59
  pattern: /child_process\.spawn\s*\(/g,
42
60
  severity: "high",
43
61
  category: "command-injection",
44
62
  cwe: "CWE-78",
63
+ hints: ["child_process"],
45
64
  },
46
65
  {
47
66
  pattern: /execSync\s*\(/g,
48
67
  severity: "high",
49
68
  category: "command-injection",
50
69
  cwe: "CWE-78",
70
+ hints: ["execSync"],
51
71
  },
52
72
  // SQL injection (if applicable)
53
73
  {
@@ -55,12 +75,14 @@ export class SecurityAuditor {
55
75
  severity: "high",
56
76
  category: "sql-injection",
57
77
  cwe: "CWE-89",
78
+ hints: ["SELECT", "+"],
58
79
  },
59
80
  {
60
81
  pattern: /INSERT.*\+/g,
61
82
  severity: "high",
62
83
  category: "sql-injection",
63
84
  cwe: "CWE-89",
85
+ hints: ["INSERT", "+"],
64
86
  },
65
87
  // Path traversal
66
88
  {
@@ -68,12 +90,14 @@ export class SecurityAuditor {
68
90
  severity: "high",
69
91
  category: "path-traversal",
70
92
  cwe: "CWE-22",
93
+ hints: [".."],
71
94
  },
72
95
  {
73
96
  pattern: /path\.join\s*\(\s*\.\./g,
74
97
  severity: "high",
75
98
  category: "path-traversal",
76
99
  cwe: "CWE-22",
100
+ hints: ["path.join", ".."],
77
101
  },
78
102
  // Hardcoded secrets
79
103
  {
@@ -81,18 +105,21 @@ export class SecurityAuditor {
81
105
  severity: "high",
82
106
  category: "hardcoded-secrets",
83
107
  cwe: "CWE-798",
108
+ hints: ["password"],
84
109
  },
85
110
  {
86
111
  pattern: /api[_-]?key\s*[:=]\s*['"][^'"]*['"]/gi,
87
112
  severity: "high",
88
113
  category: "hardcoded-secrets",
89
114
  cwe: "CWE-798",
115
+ hints: ["api"],
90
116
  },
91
117
  {
92
118
  pattern: /secret\s*[:=]\s*['"][^'"]*['"]/gi,
93
119
  severity: "high",
94
120
  category: "hardcoded-secrets",
95
121
  cwe: "CWE-798",
122
+ hints: ["secret"],
96
123
  },
97
124
  // Insecure random
98
125
  {
@@ -100,6 +127,7 @@ export class SecurityAuditor {
100
127
  severity: "medium",
101
128
  category: "weak-cryptography",
102
129
  cwe: "CWE-338",
130
+ hints: ["Math.random"],
103
131
  },
104
132
  // Console logging sensitive data
105
133
  {
@@ -107,12 +135,14 @@ export class SecurityAuditor {
107
135
  severity: "medium",
108
136
  category: "information-disclosure",
109
137
  cwe: "CWE-532",
138
+ hints: ["console.log", "password"],
110
139
  },
111
140
  {
112
141
  pattern: /console\.log\s*\([^)]*secret[^)]*\)/gi,
113
142
  severity: "medium",
114
143
  category: "information-disclosure",
115
144
  cwe: "CWE-532",
145
+ hints: ["console.log", "secret"],
116
146
  },
117
147
  // Missing input validation
118
148
  {
@@ -120,12 +150,14 @@ export class SecurityAuditor {
120
150
  severity: "medium",
121
151
  category: "input-validation",
122
152
  cwe: "CWE-20",
153
+ hints: ["req.body"],
123
154
  },
124
155
  {
125
156
  pattern: /req\.query\./g,
126
157
  severity: "medium",
127
158
  category: "input-validation",
128
159
  cwe: "CWE-20",
160
+ hints: ["req.query"],
129
161
  },
130
162
  // Insecure deserialization
131
163
  {
@@ -133,6 +165,7 @@ export class SecurityAuditor {
133
165
  severity: "medium",
134
166
  category: "deserialization",
135
167
  cwe: "CWE-502",
168
+ hints: ["JSON.parse"],
136
169
  },
137
170
  // Race conditions
138
171
  {
@@ -140,6 +173,7 @@ export class SecurityAuditor {
140
173
  severity: "low",
141
174
  category: "race-conditions",
142
175
  cwe: "CWE-362",
176
+ hints: ["setTimeout", "0"],
143
177
  },
144
178
  // Information disclosure in errors
145
179
  {
@@ -147,6 +181,7 @@ export class SecurityAuditor {
147
181
  severity: "low",
148
182
  category: "information-disclosure",
149
183
  cwe: "CWE-209",
184
+ hints: ["throw", "error", "stack"],
150
185
  },
151
186
  ];
152
187
  dangerousImports = [
@@ -161,55 +196,97 @@ export class SecurityAuditor {
161
196
  "worker_threads",
162
197
  "vm",
163
198
  ];
199
+ compiledImports = this.dangerousImports.map((name) => ({
200
+ name,
201
+ patterns: [
202
+ new RegExp(`import.*from.*['"]${name}['"]`),
203
+ new RegExp(`require\\s*\\(\\s*['"]${name}['"]\\s*\\)`),
204
+ new RegExp(`import.*${name}`),
205
+ ],
206
+ }));
207
+ textCache;
164
208
  /**
165
209
  * Run comprehensive security audit
166
210
  */
167
211
  async auditProject(projectPath = ".") {
168
212
  const jobId = `security-audit-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
169
213
  const issues = [];
170
- const files = this.getAllFiles(projectPath);
171
- frameworkLogger.log("security-auditor", "scan-start", "info", {
172
- jobId,
173
- filesCount: files.length,
174
- projectPath,
175
- });
176
- for (const file of files) {
177
- if (this.shouldAuditFile(file)) {
178
- const fileIssues = await this.auditFile(file);
179
- issues.push(...fileIssues);
214
+ this.textCache = new Map();
215
+ try {
216
+ const files = this.getAllFiles(projectPath);
217
+ frameworkLogger.log("security-auditor", "scan-start", "info", {
218
+ jobId,
219
+ filesCount: files.length,
220
+ projectPath,
221
+ });
222
+ for (const file of files) {
223
+ if (this.shouldAuditFile(file)) {
224
+ const fileIssues = await this.auditFile(file);
225
+ issues.push(...fileIssues);
226
+ }
180
227
  }
228
+ // Additional checks
229
+ issues.push(...this.auditPackageJson(projectPath));
230
+ issues.push(...this.auditConfiguration(projectPath));
231
+ issues.push(...this.auditDependencies(projectPath));
232
+ const summary = this.generateSummary(issues);
233
+ const score = this.calculateSecurityScore(issues, files.length);
234
+ return {
235
+ totalFiles: files.length,
236
+ issues,
237
+ summary,
238
+ score,
239
+ };
240
+ }
241
+ finally {
242
+ this.textCache = undefined;
181
243
  }
182
- // Additional checks
183
- issues.push(...this.auditPackageJson(projectPath));
184
- issues.push(...this.auditConfiguration(projectPath));
185
- issues.push(...this.auditDependencies(projectPath));
186
- const summary = this.generateSummary(issues);
187
- const score = this.calculateSecurityScore(issues, files.length);
188
- return {
189
- totalFiles: files.length,
190
- issues,
191
- summary,
192
- score,
193
- };
194
244
  }
195
245
  getAllFiles(dirPath) {
196
246
  const files = [];
197
247
  const traverse = (currentPath) => {
198
- const items = readdirSync(currentPath);
199
- for (const item of items) {
200
- const fullPath = join(currentPath, item);
201
- const stat = statSync(fullPath);
202
- if (stat.isDirectory() && !this.shouldSkipDirectory(item)) {
203
- traverse(fullPath);
248
+ // Dirent already knows file vs directory. Stat names and symlinks so the target type matches statSync.
249
+ const entries = readdirSync(currentPath, { withFileTypes: true });
250
+ for (const entry of entries) {
251
+ if (typeof entry === "string") {
252
+ this.visitNamed(currentPath, entry, files, traverse);
253
+ continue;
204
254
  }
205
- else if (stat.isFile()) {
206
- files.push(fullPath);
255
+ const fullPath = join(currentPath, entry.name);
256
+ if (typeof entry.isSymbolicLink === "function" && entry.isSymbolicLink()) {
257
+ this.visitNamed(currentPath, entry.name, files, traverse);
258
+ continue;
207
259
  }
260
+ if (entry.isDirectory()) {
261
+ if (!this.shouldSkipDirectory(entry.name))
262
+ traverse(fullPath);
263
+ continue;
264
+ }
265
+ if (entry.isFile())
266
+ files.push(fullPath);
208
267
  }
209
268
  };
210
269
  traverse(dirPath);
211
270
  return files;
212
271
  }
272
+ visitNamed(currentPath, name, files, traverse) {
273
+ const fullPath = join(currentPath, name);
274
+ const stat = statSync(fullPath);
275
+ if (stat.isDirectory() && !this.shouldSkipDirectory(name)) {
276
+ traverse(fullPath);
277
+ }
278
+ else if (stat.isFile()) {
279
+ files.push(fullPath);
280
+ }
281
+ }
282
+ readText(filePath) {
283
+ const cached = this.textCache?.get(filePath);
284
+ if (cached !== undefined)
285
+ return cached;
286
+ const text = readFileSync(filePath, "utf-8");
287
+ this.textCache?.set(filePath, text);
288
+ return text;
289
+ }
213
290
  shouldSkipDirectory(dirName) {
214
291
  const skipDirs = [
215
292
  "node_modules",
@@ -234,14 +311,30 @@ export class SecurityAuditor {
234
311
  async auditFile(filePath) {
235
312
  const issues = [];
236
313
  try {
237
- const content = readFileSync(filePath, "utf-8");
314
+ const content = this.readText(filePath);
238
315
  const lines = content.split("\n");
239
316
  // Pattern-based security checks
240
317
  for (let i = 0; i < lines.length; i++) {
241
318
  const line = lines[i];
242
319
  const lineNumber = i + 1;
243
- for (const { pattern, severity, category, cwe } of this
320
+ let folded;
321
+ for (const { pattern, severity, category, cwe, hints } of this
244
322
  .dangerousPatterns) {
323
+ // lastIndex carries across lines. Skip only when the search would start at 0 and a hint is absent.
324
+ if (line && pattern.lastIndex === 0) {
325
+ const hay = pattern.flags.includes("i")
326
+ ? (folded ??= line.toLowerCase())
327
+ : line;
328
+ let miss = false;
329
+ for (const hint of hints) {
330
+ if (!hay.includes(hint)) {
331
+ miss = true;
332
+ break;
333
+ }
334
+ }
335
+ if (miss)
336
+ continue;
337
+ }
245
338
  const matches = line?.match(pattern);
246
339
  if (matches && line) {
247
340
  // Skip false positives in security validation and test code
@@ -304,19 +397,15 @@ export class SecurityAuditor {
304
397
  }
305
398
  auditImports(content, filePath) {
306
399
  const issues = [];
307
- for (const dangerousImport of this.dangerousImports) {
308
- const importPatterns = [
309
- new RegExp(`import.*from.*['"]${dangerousImport}['"]`, "g"),
310
- new RegExp(`require\\s*\\(\\s*['"]${dangerousImport}['"]\\s*\\)`, "g"),
311
- new RegExp(`import.*${dangerousImport}`, "g"),
312
- ];
313
- for (const pattern of importPatterns) {
400
+ for (const { name, patterns } of this.compiledImports) {
401
+ for (const pattern of patterns) {
402
+ pattern.lastIndex = 0;
314
403
  if (pattern.test(content)) {
315
404
  issues.push({
316
405
  severity: "medium",
317
406
  category: "dangerous-imports",
318
407
  file: filePath,
319
- description: `Potentially dangerous import detected: ${dangerousImport}`,
408
+ description: `Potentially dangerous import detected: ${name}`,
320
409
  recommendation: "Review usage and ensure proper sandboxing/validation",
321
410
  cwe: "CWE-350",
322
411
  });
@@ -363,7 +452,7 @@ export class SecurityAuditor {
363
452
  const issues = [];
364
453
  try {
365
454
  const packagePath = join(projectPath, "package.json");
366
- const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
455
+ const packageJson = JSON.parse(this.readText(packagePath));
367
456
  // Check for vulnerable dependencies
368
457
  const allDeps = {
369
458
  ...packageJson.dependencies,
@@ -411,7 +500,7 @@ export class SecurityAuditor {
411
500
  for (const configFile of configFiles) {
412
501
  const configPath = join(projectPath, configFile);
413
502
  try {
414
- const content = readFileSync(configPath, "utf-8");
503
+ const content = this.readText(configPath);
415
504
  // Check for hardcoded secrets
416
505
  const secretPatterns = [
417
506
  /password\s*[:=]\s*['"][^'"]*['"]/gi,
@@ -462,21 +551,7 @@ export class SecurityAuditor {
462
551
  return issues;
463
552
  }
464
553
  getRecommendationForCategory(category) {
465
- const recommendations = {
466
- "code-injection": "Use static code analysis and avoid dynamic code execution",
467
- "command-injection": "Validate and sanitize all user inputs, use parameterized commands",
468
- "sql-injection": "Use parameterized queries or ORM with built-in protection",
469
- "path-traversal": "Validate paths, use allowlists, resolve to absolute paths",
470
- "hardcoded-secrets": "Use environment variables or secure credential management",
471
- "weak-cryptography": "Use cryptographically secure random number generators",
472
- "information-disclosure": "Avoid logging sensitive information, use proper log levels",
473
- "input-validation": "Implement comprehensive input validation and sanitization",
474
- deserialization: "Validate serialized data, use safe deserialization libraries",
475
- "race-conditions": "Use proper synchronization primitives",
476
- "dangerous-imports": "Review usage and implement proper access controls",
477
- "file-permissions": "Restrict file permissions to minimum required access",
478
- };
479
- return (recommendations[category] ||
554
+ return (RECOMMENDATIONS[category] ||
480
555
  "Review and implement appropriate security measures");
481
556
  }
482
557
  generateSummary(issues) {
@@ -18,6 +18,7 @@ export interface SecurityHardeningConfig {
18
18
  }
19
19
  export declare class SecurityHardener {
20
20
  private config;
21
+ private readonly patternCache;
21
22
  constructor(config?: Partial<SecurityHardeningConfig>);
22
23
  /**
23
24
  * Apply security hardening based on audit results
@@ -44,6 +45,7 @@ export declare class SecurityHardener {
44
45
  valid: boolean;
45
46
  errors: string[];
46
47
  };
48
+ private regexFor;
47
49
  /**
48
50
  * Check rate limiting
49
51
  */
@@ -9,6 +9,7 @@
9
9
  import { promises as fs } from "fs";
10
10
  export class SecurityHardener {
11
11
  config;
12
+ patternCache = new Map();
12
13
  constructor(config = {}) {
13
14
  this.config = {
14
15
  enableInputValidation: true,
@@ -127,7 +128,7 @@ export class SecurityHardener {
127
128
  }
128
129
  if (schema.pattern &&
129
130
  typeof input === "string" &&
130
- !new RegExp(schema.pattern).test(input)) {
131
+ !this.regexFor(String(schema.pattern)).test(input)) {
131
132
  errors.push("String does not match required pattern");
132
133
  }
133
134
  return {
@@ -135,6 +136,16 @@ export class SecurityHardener {
135
136
  errors,
136
137
  };
137
138
  }
139
+ regexFor(source) {
140
+ const cached = this.patternCache.get(source);
141
+ if (cached) {
142
+ cached.lastIndex = 0;
143
+ return cached;
144
+ }
145
+ const compiled = new RegExp(source);
146
+ this.patternCache.set(source, compiled);
147
+ return compiled;
148
+ }
138
149
  /**
139
150
  * Check rate limiting
140
151
  */
@@ -143,13 +154,27 @@ export class SecurityHardener {
143
154
  return true;
144
155
  const now = Date.now();
145
156
  const windowStart = now - this.config.rateLimitWindowMs;
146
- const userRequests = requests.get(identifier) || [];
147
- const recentRequests = userRequests.filter((time) => time > windowStart);
148
- if (recentRequests.length >= this.config.rateLimitMaxRequests) {
157
+ const userRequests = requests.get(identifier);
158
+ if (!userRequests) {
159
+ requests.set(identifier, [now]);
160
+ return true;
161
+ }
162
+ let recent = 0;
163
+ for (let i = 0; i < userRequests.length; i++) {
164
+ const time = userRequests[i];
165
+ if (time !== undefined && time > windowStart)
166
+ recent++;
167
+ }
168
+ if (recent >= this.config.rateLimitMaxRequests)
149
169
  return false;
170
+ let write = 0;
171
+ for (let i = 0; i < userRequests.length; i++) {
172
+ const time = userRequests[i];
173
+ if (time !== undefined && time > windowStart)
174
+ userRequests[write++] = time;
150
175
  }
151
- recentRequests.push(now);
152
- requests.set(identifier, recentRequests);
176
+ userRequests.length = write;
177
+ userRequests.push(now);
153
178
  return true;
154
179
  }
155
180
  /**
@@ -34,11 +34,13 @@ export interface SecurityHeadersConfig {
34
34
  }
35
35
  export declare class SecurityHeadersMiddleware {
36
36
  private config;
37
+ private headerPairs;
37
38
  constructor(config?: Partial<SecurityHeadersConfig>);
38
39
  /**
39
40
  * Apply security headers to HTTP response
40
41
  */
41
42
  applySecurityHeaders(response: HttpResponse): void;
43
+ private rebuildHeaders;
42
44
  /**
43
45
  * Express.js middleware function
44
46
  */
@@ -9,6 +9,7 @@
9
9
  import { frameworkLogger } from "../core/framework-logger.js";
10
10
  export class SecurityHeadersMiddleware {
11
11
  config;
12
+ headerPairs = [];
12
13
  constructor(config = {}) {
13
14
  this.config = {
14
15
  enableCSP: true,
@@ -23,6 +24,7 @@ export class SecurityHeadersMiddleware {
23
24
  hstsPreload: false,
24
25
  ...config,
25
26
  };
27
+ this.rebuildHeaders();
26
28
  }
27
29
  /**
28
30
  * Apply security headers to HTTP response
@@ -32,14 +34,19 @@ export class SecurityHeadersMiddleware {
32
34
  frameworkLogger.log("security-headers", "invalid-response-object", "warning", { warning: "SecurityHeadersMiddleware: Invalid response object" });
33
35
  return;
34
36
  }
35
- const headers = {};
36
- // Content Security Policy
37
+ for (const [key, value] of this.headerPairs) {
38
+ response.setHeader(key, value);
39
+ }
40
+ }
41
+ rebuildHeaders() {
42
+ const headers = [];
37
43
  if (this.config.enableCSP) {
38
- headers["Content-Security-Policy"] =
44
+ headers.push([
45
+ "Content-Security-Policy",
39
46
  this.config.customCSP ||
40
- "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'";
47
+ "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'",
48
+ ]);
41
49
  }
42
- // HTTP Strict Transport Security
43
50
  if (this.config.enableHSTS) {
44
51
  let hstsValue = `max-age=${this.config.hstsMaxAge}`;
45
52
  if (this.config.hstsIncludeSubdomains) {
@@ -48,33 +55,27 @@ export class SecurityHeadersMiddleware {
48
55
  if (this.config.hstsPreload) {
49
56
  hstsValue += "; preload";
50
57
  }
51
- headers["Strict-Transport-Security"] = hstsValue;
58
+ headers.push(["Strict-Transport-Security", hstsValue]);
52
59
  }
53
- // X-Frame-Options
54
60
  if (this.config.enableFrameOptions) {
55
- headers["X-Frame-Options"] = "DENY";
61
+ headers.push(["X-Frame-Options", "DENY"]);
56
62
  }
57
- // X-XSS-Protection
58
63
  if (this.config.enableXSSProtection) {
59
- headers["X-XSS-Protection"] = "1; mode=block";
64
+ headers.push(["X-XSS-Protection", "1; mode=block"]);
60
65
  }
61
- // X-Content-Type-Options
62
66
  if (this.config.enableContentTypeOptions) {
63
- headers["X-Content-Type-Options"] = "nosniff";
67
+ headers.push(["X-Content-Type-Options", "nosniff"]);
64
68
  }
65
- // Referrer-Policy
66
69
  if (this.config.enableReferrerPolicy) {
67
- headers["Referrer-Policy"] = "strict-origin-when-cross-origin";
70
+ headers.push(["Referrer-Policy", "strict-origin-when-cross-origin"]);
68
71
  }
69
- // Permissions-Policy
70
72
  if (this.config.enablePermissionsPolicy) {
71
- headers["Permissions-Policy"] =
72
- "geolocation=(), microphone=(), camera=()";
73
+ headers.push([
74
+ "Permissions-Policy",
75
+ "geolocation=(), microphone=(), camera=()",
76
+ ]);
73
77
  }
74
- // Set headers on response
75
- Object.entries(headers).forEach(([key, value]) => {
76
- response.setHeader(key, value);
77
- });
78
+ this.headerPairs = headers;
78
79
  }
79
80
  /**
80
81
  * Express.js middleware function
@@ -105,6 +106,7 @@ export class SecurityHeadersMiddleware {
105
106
  */
106
107
  updateConfig(newConfig) {
107
108
  this.config = { ...this.config, ...newConfig };
109
+ this.rebuildHeaders();
108
110
  }
109
111
  /**
110
112
  * Get current configuration
@@ -243,16 +243,30 @@ export class SecurityScanner {
243
243
  */
244
244
  generateRecommendations(vulnerabilities) {
245
245
  const recommendations = [];
246
- if (vulnerabilities.some((v) => v.severity === "critical")) {
246
+ let critical = false;
247
+ let high = false;
248
+ let packaged = false;
249
+ let eslint = false;
250
+ for (const vuln of vulnerabilities) {
251
+ if (vuln.severity === "critical")
252
+ critical = true;
253
+ else if (vuln.severity === "high")
254
+ high = true;
255
+ if (vuln.package)
256
+ packaged = true;
257
+ if (vuln.id.includes("eslint"))
258
+ eslint = true;
259
+ }
260
+ if (critical) {
247
261
  recommendations.push("🚨 Critical security vulnerabilities found - immediate action required");
248
262
  }
249
- if (vulnerabilities.some((v) => v.severity === "high")) {
263
+ if (high) {
250
264
  recommendations.push("⚠️ High-severity vulnerabilities detected - prioritize fixes");
251
265
  }
252
- if (vulnerabilities.filter((v) => v.package).length > 0) {
266
+ if (packaged) {
253
267
  recommendations.push("📦 Update vulnerable dependencies to latest secure versions");
254
268
  }
255
- if (vulnerabilities.filter((v) => v.id.includes("eslint")).length > 0) {
269
+ if (eslint) {
256
270
  recommendations.push("🔧 Fix code security issues identified by ESLint");
257
271
  }
258
272
  recommendations.push("🔍 Run regular security scans and keep dependencies updated");
@@ -37,6 +37,8 @@ export declare class SessionCleanupManager {
37
37
  private cleanupInterval?;
38
38
  private _sessionMetadata?;
39
39
  private _metadataLoaded;
40
+ /** Same object the store holds, so a one-field write does not clone every session. */
41
+ private metadataRecord;
40
42
  private sessionMonitor;
41
43
  constructor(stateManager: XrayStateManager, config?: Partial<CleanupConfig>, sessionMonitor?: SessionMonitor);
42
44
  /**