mcp-adr-analysis-server 2.0.21 → 2.1.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 (263) hide show
  1. package/README.md +94 -839
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/config/ai-config.d.ts.map +1 -1
  4. package/dist/src/config/ai-config.js +9 -9
  5. package/dist/src/config/ai-config.js.map +1 -1
  6. package/dist/src/index.d.ts +15 -0
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/index.js +1594 -837
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/prompts/analysis-prompts.d.ts +4 -1
  11. package/dist/src/prompts/analysis-prompts.d.ts.map +1 -1
  12. package/dist/src/prompts/analysis-prompts.js +61 -30
  13. package/dist/src/prompts/analysis-prompts.js.map +1 -1
  14. package/dist/src/prompts/index.d.ts +17 -1
  15. package/dist/src/prompts/index.d.ts.map +1 -1
  16. package/dist/src/prompts/index.js +325 -1
  17. package/dist/src/prompts/index.js.map +1 -1
  18. package/dist/src/prompts/rule-generation-prompts.d.ts +5 -1
  19. package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -1
  20. package/dist/src/prompts/rule-generation-prompts.js +5 -1
  21. package/dist/src/prompts/rule-generation-prompts.js.map +1 -1
  22. package/dist/src/prompts/security-prompts.d.ts +6 -1
  23. package/dist/src/prompts/security-prompts.d.ts.map +1 -1
  24. package/dist/src/prompts/security-prompts.js +6 -1
  25. package/dist/src/prompts/security-prompts.js.map +1 -1
  26. package/dist/src/prompts/todo-prompts.d.ts +49 -0
  27. package/dist/src/prompts/todo-prompts.d.ts.map +1 -0
  28. package/dist/src/prompts/todo-prompts.js +824 -0
  29. package/dist/src/prompts/todo-prompts.js.map +1 -0
  30. package/dist/src/resources/index.d.ts.map +1 -1
  31. package/dist/src/resources/index.js +9 -7
  32. package/dist/src/resources/index.js.map +1 -1
  33. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts +47 -0
  34. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts.map +1 -0
  35. package/dist/src/tools/adr-bootstrap-validation-tool.js +979 -0
  36. package/dist/src/tools/adr-bootstrap-validation-tool.js.map +1 -0
  37. package/dist/src/tools/adr-suggestion-tool.d.ts +1 -0
  38. package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
  39. package/dist/src/tools/adr-suggestion-tool.js +330 -32
  40. package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
  41. package/dist/src/tools/content-masking-tool.d.ts +5 -0
  42. package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
  43. package/dist/src/tools/content-masking-tool.js +631 -28
  44. package/dist/src/tools/content-masking-tool.js.map +1 -1
  45. package/dist/src/tools/deployment-readiness-tool.d.ts +8 -5
  46. package/dist/src/tools/deployment-readiness-tool.d.ts.map +1 -1
  47. package/dist/src/tools/deployment-readiness-tool.js +1017 -93
  48. package/dist/src/tools/deployment-readiness-tool.js.map +1 -1
  49. package/dist/src/tools/environment-analysis-tool.d.ts +4 -0
  50. package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
  51. package/dist/src/tools/environment-analysis-tool.js +568 -24
  52. package/dist/src/tools/environment-analysis-tool.js.map +1 -1
  53. package/dist/src/tools/interactive-adr-planning-tool.d.ts.map +1 -1
  54. package/dist/src/tools/interactive-adr-planning-tool.js +270 -108
  55. package/dist/src/tools/interactive-adr-planning-tool.js.map +1 -1
  56. package/dist/src/tools/mcp-planning-tool.d.ts.map +1 -1
  57. package/dist/src/tools/mcp-planning-tool.js +316 -183
  58. package/dist/src/tools/mcp-planning-tool.js.map +1 -1
  59. package/dist/src/tools/memory-loading-tool.d.ts +60 -0
  60. package/dist/src/tools/memory-loading-tool.d.ts.map +1 -0
  61. package/dist/src/tools/memory-loading-tool.js +457 -0
  62. package/dist/src/tools/memory-loading-tool.js.map +1 -0
  63. package/dist/src/tools/research-integration-tool.d.ts +4 -1
  64. package/dist/src/tools/research-integration-tool.d.ts.map +1 -1
  65. package/dist/src/tools/research-integration-tool.js +5 -1
  66. package/dist/src/tools/research-integration-tool.js.map +1 -1
  67. package/dist/src/tools/review-existing-adrs-tool.d.ts +19 -0
  68. package/dist/src/tools/review-existing-adrs-tool.d.ts.map +1 -0
  69. package/dist/src/tools/review-existing-adrs-tool.js +1204 -0
  70. package/dist/src/tools/review-existing-adrs-tool.js.map +1 -0
  71. package/dist/src/tools/rule-generation-tool.d.ts +2 -0
  72. package/dist/src/tools/rule-generation-tool.d.ts.map +1 -1
  73. package/dist/src/tools/rule-generation-tool.js +274 -33
  74. package/dist/src/tools/rule-generation-tool.js.map +1 -1
  75. package/dist/src/tools/smart-git-push-tool-v2.d.ts +4 -0
  76. package/dist/src/tools/smart-git-push-tool-v2.d.ts.map +1 -1
  77. package/dist/src/tools/smart-git-push-tool-v2.js +423 -229
  78. package/dist/src/tools/smart-git-push-tool-v2.js.map +1 -1
  79. package/dist/src/tools/smart-git-push-tool.d.ts +3 -0
  80. package/dist/src/tools/smart-git-push-tool.d.ts.map +1 -1
  81. package/dist/src/tools/smart-git-push-tool.js +241 -235
  82. package/dist/src/tools/smart-git-push-tool.js.map +1 -1
  83. package/dist/src/tools/tool-chain-orchestrator.d.ts +2 -2
  84. package/dist/src/tools/tool-chain-orchestrator.d.ts.map +1 -1
  85. package/dist/src/tools/tool-chain-orchestrator.js +152 -93
  86. package/dist/src/tools/tool-chain-orchestrator.js.map +1 -1
  87. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +22 -13
  88. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
  89. package/dist/src/tools/troubleshoot-guided-workflow-tool.js +660 -28
  90. package/dist/src/tools/troubleshoot-guided-workflow-tool.js.map +1 -1
  91. package/dist/src/types/ape-framework.d.ts +93 -0
  92. package/dist/src/types/ape-framework.d.ts.map +1 -1
  93. package/dist/src/types/ape-framework.js +10 -10
  94. package/dist/src/types/ape-framework.js.map +1 -1
  95. package/dist/src/types/enhanced-errors.d.ts +173 -0
  96. package/dist/src/types/enhanced-errors.d.ts.map +1 -0
  97. package/dist/src/types/enhanced-errors.js +668 -0
  98. package/dist/src/types/enhanced-errors.js.map +1 -0
  99. package/dist/src/types/index.d.ts +129 -3
  100. package/dist/src/types/index.d.ts.map +1 -1
  101. package/dist/src/types/index.js +15 -0
  102. package/dist/src/types/index.js.map +1 -1
  103. package/dist/src/types/knowledge-generation.d.ts +78 -0
  104. package/dist/src/types/knowledge-generation.d.ts.map +1 -1
  105. package/dist/src/types/knowledge-generation.js +10 -6
  106. package/dist/src/types/knowledge-generation.js.map +1 -1
  107. package/dist/src/types/knowledge-graph-schemas.d.ts +92 -0
  108. package/dist/src/types/knowledge-graph-schemas.d.ts.map +1 -1
  109. package/dist/src/types/knowledge-graph-schemas.js +45 -17
  110. package/dist/src/types/knowledge-graph-schemas.js.map +1 -1
  111. package/dist/src/types/memory-entities.d.ts +7209 -0
  112. package/dist/src/types/memory-entities.d.ts.map +1 -0
  113. package/dist/src/types/memory-entities.js +395 -0
  114. package/dist/src/types/memory-entities.js.map +1 -0
  115. package/dist/src/types/reflexion-framework.d.ts +44 -0
  116. package/dist/src/types/reflexion-framework.d.ts.map +1 -1
  117. package/dist/src/types/reflexion-framework.js +7 -7
  118. package/dist/src/types/reflexion-framework.js.map +1 -1
  119. package/dist/src/types/todo-json-schemas.d.ts +7 -653
  120. package/dist/src/types/todo-json-schemas.d.ts.map +1 -1
  121. package/dist/src/types/todo-json-schemas.js +6 -110
  122. package/dist/src/types/todo-json-schemas.js.map +1 -1
  123. package/dist/src/types/tool-arguments.d.ts +224 -0
  124. package/dist/src/types/tool-arguments.d.ts.map +1 -0
  125. package/dist/src/types/tool-arguments.js +6 -0
  126. package/dist/src/types/tool-arguments.js.map +1 -0
  127. package/dist/src/utils/actual-file-operations.d.ts.map +1 -1
  128. package/dist/src/utils/actual-file-operations.js +25 -9
  129. package/dist/src/utils/actual-file-operations.js.map +1 -1
  130. package/dist/src/utils/adr-discovery.d.ts +33 -1
  131. package/dist/src/utils/adr-discovery.d.ts.map +1 -1
  132. package/dist/src/utils/adr-discovery.js +14 -9
  133. package/dist/src/utils/adr-discovery.js.map +1 -1
  134. package/dist/src/utils/adr-suggestions.d.ts +72 -0
  135. package/dist/src/utils/adr-suggestions.d.ts.map +1 -1
  136. package/dist/src/utils/adr-suggestions.js +6 -0
  137. package/dist/src/utils/adr-suggestions.js.map +1 -1
  138. package/dist/src/utils/cache.d.ts.map +1 -1
  139. package/dist/src/utils/cache.js +22 -19
  140. package/dist/src/utils/cache.js.map +1 -1
  141. package/dist/src/utils/chain-of-thought-template.d.ts +13 -1
  142. package/dist/src/utils/chain-of-thought-template.d.ts.map +1 -1
  143. package/dist/src/utils/chain-of-thought-template.js +31 -22
  144. package/dist/src/utils/chain-of-thought-template.js.map +1 -1
  145. package/dist/src/utils/config.d.ts.map +1 -1
  146. package/dist/src/utils/config.js +1 -0
  147. package/dist/src/utils/config.js.map +1 -1
  148. package/dist/src/utils/directory-compat.js +1 -1
  149. package/dist/src/utils/directory-compat.js.map +1 -1
  150. package/dist/src/utils/enhanced-logging.d.ts +195 -0
  151. package/dist/src/utils/enhanced-logging.d.ts.map +1 -0
  152. package/dist/src/utils/enhanced-logging.js +449 -0
  153. package/dist/src/utils/enhanced-logging.js.map +1 -0
  154. package/dist/src/utils/file-system.d.ts +182 -34
  155. package/dist/src/utils/file-system.d.ts.map +1 -1
  156. package/dist/src/utils/file-system.js +648 -774
  157. package/dist/src/utils/file-system.js.map +1 -1
  158. package/dist/src/utils/gitleaks-detector.d.ts +50 -0
  159. package/dist/src/utils/gitleaks-detector.d.ts.map +1 -0
  160. package/dist/src/utils/gitleaks-detector.js +334 -0
  161. package/dist/src/utils/gitleaks-detector.js.map +1 -0
  162. package/dist/src/utils/interactive-approval.d.ts +1 -1
  163. package/dist/src/utils/interactive-approval.d.ts.map +1 -1
  164. package/dist/src/utils/interactive-approval.js +22 -17
  165. package/dist/src/utils/interactive-approval.js.map +1 -1
  166. package/dist/src/utils/json-safe.d.ts.map +1 -1
  167. package/dist/src/utils/json-safe.js +9 -6
  168. package/dist/src/utils/json-safe.js.map +1 -1
  169. package/dist/src/utils/knowledge-graph-manager.d.ts +37 -1
  170. package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
  171. package/dist/src/utils/knowledge-graph-manager.js +315 -70
  172. package/dist/src/utils/knowledge-graph-manager.js.map +1 -1
  173. package/dist/src/utils/location-filter.d.ts +35 -10
  174. package/dist/src/utils/location-filter.d.ts.map +1 -1
  175. package/dist/src/utils/location-filter.js +360 -94
  176. package/dist/src/utils/location-filter.js.map +1 -1
  177. package/dist/src/utils/mcp-response-validator.d.ts.map +1 -1
  178. package/dist/src/utils/mcp-response-validator.js +34 -19
  179. package/dist/src/utils/mcp-response-validator.js.map +1 -1
  180. package/dist/src/utils/memory-entity-manager.d.ts +134 -0
  181. package/dist/src/utils/memory-entity-manager.d.ts.map +1 -0
  182. package/dist/src/utils/memory-entity-manager.js +851 -0
  183. package/dist/src/utils/memory-entity-manager.js.map +1 -0
  184. package/dist/src/utils/memory-health-scoring.d.ts +125 -0
  185. package/dist/src/utils/memory-health-scoring.d.ts.map +1 -0
  186. package/dist/src/utils/memory-health-scoring.js +277 -0
  187. package/dist/src/utils/memory-health-scoring.js.map +1 -0
  188. package/dist/src/utils/memory-migration-manager.d.ts +93 -0
  189. package/dist/src/utils/memory-migration-manager.d.ts.map +1 -0
  190. package/dist/src/utils/memory-migration-manager.js +842 -0
  191. package/dist/src/utils/memory-migration-manager.js.map +1 -0
  192. package/dist/src/utils/memory-relationship-mapper.d.ts +87 -0
  193. package/dist/src/utils/memory-relationship-mapper.d.ts.map +1 -0
  194. package/dist/src/utils/memory-relationship-mapper.js +482 -0
  195. package/dist/src/utils/memory-relationship-mapper.js.map +1 -0
  196. package/dist/src/utils/memory-rollback-manager.d.ts +105 -0
  197. package/dist/src/utils/memory-rollback-manager.d.ts.map +1 -0
  198. package/dist/src/utils/memory-rollback-manager.js +575 -0
  199. package/dist/src/utils/memory-rollback-manager.js.map +1 -0
  200. package/dist/src/utils/memory-transformation.d.ts +59 -0
  201. package/dist/src/utils/memory-transformation.d.ts.map +1 -0
  202. package/dist/src/utils/memory-transformation.js +742 -0
  203. package/dist/src/utils/memory-transformation.js.map +1 -0
  204. package/dist/src/utils/output-masking.d.ts +12 -0
  205. package/dist/src/utils/output-masking.d.ts.map +1 -1
  206. package/dist/src/utils/output-masking.js +5 -0
  207. package/dist/src/utils/output-masking.js.map +1 -1
  208. package/dist/src/utils/prompt-execution.d.ts.map +1 -1
  209. package/dist/src/utils/prompt-execution.js +72 -51
  210. package/dist/src/utils/prompt-execution.js.map +1 -1
  211. package/dist/src/utils/release-readiness-detector.d.ts.map +1 -1
  212. package/dist/src/utils/release-readiness-detector.js +43 -42
  213. package/dist/src/utils/release-readiness-detector.js.map +1 -1
  214. package/dist/src/utils/research-integration.d.ts.map +1 -1
  215. package/dist/src/utils/research-integration.js +73 -44
  216. package/dist/src/utils/research-integration.js.map +1 -1
  217. package/dist/src/utils/research-questions.d.ts.map +1 -1
  218. package/dist/src/utils/research-questions.js +40 -14
  219. package/dist/src/utils/research-questions.js.map +1 -1
  220. package/dist/src/utils/ripgrep-wrapper.d.ts +84 -0
  221. package/dist/src/utils/ripgrep-wrapper.d.ts.map +1 -0
  222. package/dist/src/utils/ripgrep-wrapper.js +255 -0
  223. package/dist/src/utils/ripgrep-wrapper.js.map +1 -0
  224. package/dist/src/utils/rule-generation.d.ts.map +1 -1
  225. package/dist/src/utils/rule-generation.js +26 -15
  226. package/dist/src/utils/rule-generation.js.map +1 -1
  227. package/dist/src/utils/todo-file-watcher.d.ts +11 -23
  228. package/dist/src/utils/todo-file-watcher.d.ts.map +1 -1
  229. package/dist/src/utils/todo-file-watcher.js +18 -156
  230. package/dist/src/utils/todo-file-watcher.js.map +1 -1
  231. package/dist/src/utils/tree-sitter-analyzer.d.ts +185 -0
  232. package/dist/src/utils/tree-sitter-analyzer.d.ts.map +1 -0
  233. package/dist/src/utils/tree-sitter-analyzer.js +885 -0
  234. package/dist/src/utils/tree-sitter-analyzer.js.map +1 -0
  235. package/package.json +51 -10
  236. package/dist/src/tools/smart-score-tool.d.ts +0 -173
  237. package/dist/src/tools/smart-score-tool.d.ts.map +0 -1
  238. package/dist/src/tools/smart-score-tool.js +0 -681
  239. package/dist/src/tools/smart-score-tool.js.map +0 -1
  240. package/dist/src/tools/todo-management-tool-v2.d.ts +0 -368
  241. package/dist/src/tools/todo-management-tool-v2.d.ts.map +0 -1
  242. package/dist/src/tools/todo-management-tool-v2.js +0 -922
  243. package/dist/src/tools/todo-management-tool-v2.js.map +0 -1
  244. package/dist/src/utils/enhanced-sensitive-detector.d.ts +0 -61
  245. package/dist/src/utils/enhanced-sensitive-detector.d.ts.map +0 -1
  246. package/dist/src/utils/enhanced-sensitive-detector.js +0 -437
  247. package/dist/src/utils/enhanced-sensitive-detector.js.map +0 -1
  248. package/dist/src/utils/project-health-scoring.d.ts +0 -177
  249. package/dist/src/utils/project-health-scoring.d.ts.map +0 -1
  250. package/dist/src/utils/project-health-scoring.js +0 -370
  251. package/dist/src/utils/project-health-scoring.js.map +0 -1
  252. package/dist/src/utils/todo-json-manager.d.ts +0 -71
  253. package/dist/src/utils/todo-json-manager.d.ts.map +0 -1
  254. package/dist/src/utils/todo-json-manager.js +0 -396
  255. package/dist/src/utils/todo-json-manager.js.map +0 -1
  256. package/dist/src/utils/todo-markdown-converter.d.ts +0 -16
  257. package/dist/src/utils/todo-markdown-converter.d.ts.map +0 -1
  258. package/dist/src/utils/todo-markdown-converter.js +0 -362
  259. package/dist/src/utils/todo-markdown-converter.js.map +0 -1
  260. package/dist/src/utils/todo-migration.d.ts +0 -47
  261. package/dist/src/utils/todo-migration.d.ts.map +0 -1
  262. package/dist/src/utils/todo-migration.js +0 -261
  263. package/dist/src/utils/todo-migration.js.map +0 -1
@@ -0,0 +1,885 @@
1
+ /**
2
+ * Tree-sitter Integration for Enterprise DevOps Code Analysis
3
+ *
4
+ * Provides intelligent code analysis for multi-language DevOps stacks including:
5
+ * - Ansible playbooks and roles
6
+ * - Terraform/HCL infrastructure
7
+ * - Python microservices
8
+ * - Node.js applications
9
+ * - Container configurations
10
+ * - CI/CD pipelines
11
+ *
12
+ * Enterprise Features:
13
+ * - Secret detection in code
14
+ * - Architectural boundary validation
15
+ * - Multi-language dependency analysis
16
+ * - Security pattern recognition
17
+ */
18
+ import { readFileSync } from 'fs';
19
+ import { extname, basename } from 'path';
20
+ /**
21
+ * Main Tree-sitter analyzer class for enterprise DevOps stacks
22
+ */
23
+ export class TreeSitterAnalyzer {
24
+ parsers = new Map();
25
+ initialized = false;
26
+ constructor() {
27
+ this.initializeParsers();
28
+ }
29
+ /**
30
+ * Initialize tree-sitter parsers with graceful fallback
31
+ */
32
+ async initializeParsers() {
33
+ try {
34
+ // Initialize core parsers for enterprise stack
35
+ await this.loadParser('typescript', 'tree-sitter-typescript');
36
+ await this.loadParser('javascript', 'tree-sitter-javascript');
37
+ await this.loadParser('python', 'tree-sitter-python');
38
+ await this.loadParser('yaml', 'tree-sitter-yaml');
39
+ await this.loadParser('json', 'tree-sitter-json');
40
+ await this.loadParser('bash', 'tree-sitter-bash');
41
+ await this.loadParser('dockerfile', 'tree-sitter-dockerfile');
42
+ await this.loadParser('hcl', '@tree-sitter-grammars/tree-sitter-hcl');
43
+ this.initialized = true;
44
+ }
45
+ catch (error) {
46
+ console.warn('Tree-sitter initialization failed, falling back to regex analysis:', error);
47
+ this.initialized = false;
48
+ }
49
+ }
50
+ async loadParser(language, packageName) {
51
+ try {
52
+ const TreeSitterModule = await import('tree-sitter');
53
+ const TreeSitter = TreeSitterModule.default || TreeSitterModule;
54
+ let Parser;
55
+ if (language === 'typescript') {
56
+ const tsModule = await import('tree-sitter-typescript');
57
+ Parser = tsModule.typescript;
58
+ }
59
+ else if (language === 'hcl') {
60
+ const hclModule = await import('@tree-sitter-grammars/tree-sitter-hcl');
61
+ Parser = hclModule.default || hclModule;
62
+ }
63
+ else {
64
+ const module = await import(packageName);
65
+ Parser = module.default || module;
66
+ }
67
+ const parser = new TreeSitter();
68
+ parser.setLanguage(Parser);
69
+ this.parsers.set(language, parser);
70
+ }
71
+ catch (error) {
72
+ console.warn(`Failed to load ${language} parser:`, error);
73
+ }
74
+ }
75
+ /**
76
+ * Analyze code file with tree-sitter intelligence
77
+ */
78
+ async analyzeFile(filePath, content) {
79
+ const fileContent = content || readFileSync(filePath, 'utf-8');
80
+ const language = this.detectLanguage(filePath);
81
+ if (!this.initialized || !this.parsers.has(language)) {
82
+ return this.fallbackAnalysis(filePath, fileContent, language);
83
+ }
84
+ try {
85
+ const parser = this.parsers.get(language);
86
+ const tree = parser.parse(fileContent);
87
+ return await this.performIntelligentAnalysis(tree, fileContent, language, filePath);
88
+ }
89
+ catch (error) {
90
+ console.warn(`Tree-sitter analysis failed for ${filePath}, falling back to regex:`, error);
91
+ return this.fallbackAnalysis(filePath, fileContent, language);
92
+ }
93
+ }
94
+ /**
95
+ * Detect programming language from file extension and content
96
+ */
97
+ detectLanguage(filePath) {
98
+ const ext = extname(filePath).toLowerCase();
99
+ const filename = basename(filePath).toLowerCase();
100
+ // DevOps file detection
101
+ if (filename === 'dockerfile' || filename.startsWith('dockerfile.'))
102
+ return 'dockerfile';
103
+ if (filename.endsWith('.tf') || filename.endsWith('.tfvars'))
104
+ return 'hcl';
105
+ if (filename.includes('docker-compose') && (ext === '.yml' || ext === '.yaml'))
106
+ return 'yaml';
107
+ if (filename.includes('ansible') || filename.includes('playbook'))
108
+ return 'yaml';
109
+ if (filename.includes('k8s') || filename.includes('kubernetes'))
110
+ return 'yaml';
111
+ // Standard language detection
112
+ switch (ext) {
113
+ case '.ts':
114
+ case '.tsx':
115
+ return 'typescript';
116
+ case '.js':
117
+ case '.jsx':
118
+ case '.mjs':
119
+ return 'javascript';
120
+ case '.py':
121
+ case '.pyi':
122
+ return 'python';
123
+ case '.yml':
124
+ case '.yaml':
125
+ return 'yaml';
126
+ case '.json':
127
+ return 'json';
128
+ case '.sh':
129
+ case '.bash':
130
+ return 'bash';
131
+ case '.tf':
132
+ case '.tfvars':
133
+ return 'hcl';
134
+ default:
135
+ return 'text';
136
+ }
137
+ }
138
+ /**
139
+ * Perform intelligent analysis using tree-sitter AST
140
+ */
141
+ async performIntelligentAnalysis(tree, content, language, filePath) {
142
+ const lines = content.split('\n');
143
+ const result = {
144
+ language,
145
+ hasSecrets: false,
146
+ secrets: [],
147
+ imports: [],
148
+ functions: [],
149
+ variables: [],
150
+ infraStructure: [],
151
+ securityIssues: [],
152
+ architecturalViolations: [],
153
+ };
154
+ // Language-specific analysis
155
+ switch (language) {
156
+ case 'python':
157
+ await this.analyzePython(tree.rootNode, lines, result);
158
+ break;
159
+ case 'typescript':
160
+ case 'javascript':
161
+ await this.analyzeJavaScript(tree.rootNode, lines, result);
162
+ break;
163
+ case 'yaml':
164
+ await this.analyzeYAML(tree.rootNode, lines, result, filePath);
165
+ break;
166
+ case 'hcl':
167
+ await this.analyzeTerraform(tree.rootNode, lines, result);
168
+ break;
169
+ case 'dockerfile':
170
+ await this.analyzeDockerfile(tree.rootNode, lines, result);
171
+ break;
172
+ case 'bash':
173
+ await this.analyzeBash(tree.rootNode, lines, result);
174
+ break;
175
+ case 'json':
176
+ await this.analyzeJSON(tree.rootNode, lines, result);
177
+ break;
178
+ }
179
+ // Universal security analysis
180
+ await this.analyzeSecrets(tree.rootNode, lines, result);
181
+ result.hasSecrets = result.secrets.length > 0;
182
+ return result;
183
+ }
184
+ /**
185
+ * Python-specific analysis for microservices
186
+ */
187
+ async analyzePython(node, _lines, result) {
188
+ // Find imports
189
+ const imports = node
190
+ .descendantsOfType('import_statement')
191
+ .concat(node.descendantsOfType('import_from_statement'));
192
+ for (const importNode of imports) {
193
+ const importText = importNode.text;
194
+ const location = {
195
+ line: importNode.startPosition.row + 1,
196
+ column: importNode.startPosition.column,
197
+ };
198
+ // Check for dangerous imports
199
+ const isDangerous = this.checkDangerousImport(importText, 'python');
200
+ result.imports.push({
201
+ module: importText,
202
+ type: 'import',
203
+ location,
204
+ isExternal: !importText.includes('.'),
205
+ isDangerous,
206
+ ...(isDangerous && { reason: 'Potentially dangerous module' }),
207
+ });
208
+ }
209
+ // Find functions
210
+ const functions = node.descendantsOfType('function_definition');
211
+ for (const funcNode of functions) {
212
+ const nameNode = funcNode.childForFieldName('name');
213
+ if (nameNode) {
214
+ result.functions.push({
215
+ name: nameNode.text,
216
+ type: 'function',
217
+ parameters: this.extractPythonParameters(funcNode),
218
+ location: { line: funcNode.startPosition.row + 1, column: funcNode.startPosition.column },
219
+ complexity: this.calculateComplexity(funcNode),
220
+ securitySensitive: this.isSecuritySensitive(nameNode.text),
221
+ });
222
+ }
223
+ }
224
+ // Find variable assignments with potential secrets
225
+ const assignments = node.descendantsOfType('assignment');
226
+ for (const assignment of assignments) {
227
+ const leftNode = assignment.children[0];
228
+ const rightNode = assignment.children[2];
229
+ if (leftNode && rightNode) {
230
+ const varName = leftNode.text;
231
+ const varValue = rightNode.text;
232
+ result.variables.push({
233
+ name: varName,
234
+ type: 'var',
235
+ value: varValue,
236
+ location: {
237
+ line: assignment.startPosition.row + 1,
238
+ column: assignment.startPosition.column,
239
+ },
240
+ isSensitive: this.isSensitiveVariable(varName, varValue),
241
+ scope: 'module',
242
+ });
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * JavaScript/TypeScript analysis for Node.js applications
248
+ */
249
+ async analyzeJavaScript(node, _lines, result) {
250
+ // Find imports and requires
251
+ const imports = node
252
+ .descendantsOfType('import_statement')
253
+ .concat(node.descendantsOfType('call_expression'));
254
+ for (const importNode of imports) {
255
+ if (importNode.type === 'call_expression') {
256
+ const funcName = importNode.children[0]?.text;
257
+ if (funcName === 'require' && importNode.children[1]) {
258
+ const moduleNode = importNode.children[1].children[1]; // Get string content
259
+ if (moduleNode) {
260
+ result.imports.push({
261
+ module: moduleNode.text.replace(/['"]/g, ''),
262
+ type: 'require',
263
+ location: {
264
+ line: importNode.startPosition.row + 1,
265
+ column: importNode.startPosition.column,
266
+ },
267
+ isExternal: !moduleNode.text.includes('./'),
268
+ isDangerous: this.checkDangerousImport(moduleNode.text, 'javascript'),
269
+ });
270
+ }
271
+ }
272
+ }
273
+ else {
274
+ // ES6 import
275
+ const moduleNode = importNode.childForFieldName('source');
276
+ if (moduleNode) {
277
+ result.imports.push({
278
+ module: moduleNode.text.replace(/['"]/g, ''),
279
+ type: 'import',
280
+ location: {
281
+ line: importNode.startPosition.row + 1,
282
+ column: importNode.startPosition.column,
283
+ },
284
+ isExternal: !moduleNode.text.includes('./'),
285
+ isDangerous: this.checkDangerousImport(moduleNode.text, 'javascript'),
286
+ });
287
+ }
288
+ }
289
+ }
290
+ // Find functions and methods
291
+ const functions = node
292
+ .descendantsOfType('function_declaration')
293
+ .concat(node.descendantsOfType('method_definition'), node.descendantsOfType('arrow_function'));
294
+ for (const funcNode of functions) {
295
+ const nameNode = funcNode.childForFieldName('name');
296
+ const name = nameNode?.text || 'anonymous';
297
+ result.functions.push({
298
+ name,
299
+ type: funcNode.type === 'method_definition' ? 'method' : 'function',
300
+ parameters: this.extractJSParameters(funcNode),
301
+ location: { line: funcNode.startPosition.row + 1, column: funcNode.startPosition.column },
302
+ complexity: this.calculateComplexity(funcNode),
303
+ securitySensitive: this.isSecuritySensitive(name),
304
+ });
305
+ }
306
+ }
307
+ /**
308
+ * YAML analysis for Ansible, Kubernetes, Docker Compose
309
+ */
310
+ async analyzeYAML(node, _lines, result, filePath) {
311
+ // Detect YAML type based on content and filename
312
+ const content = _lines.join('\n');
313
+ const filename = basename(filePath).toLowerCase();
314
+ if (this.isAnsibleFile(filename, content)) {
315
+ await this.analyzeAnsibleYAML(node, _lines, result);
316
+ }
317
+ else if (this.isKubernetesFile(filename, content)) {
318
+ await this.analyzeKubernetesYAML(node, _lines, result);
319
+ }
320
+ else if (this.isDockerComposeFile(filename, content)) {
321
+ await this.analyzeDockerComposeYAML(node, _lines, result);
322
+ }
323
+ }
324
+ /**
325
+ * Terraform/HCL analysis for infrastructure
326
+ */
327
+ async analyzeTerraform(node, _lines, result) {
328
+ // Find resource blocks
329
+ const resources = node.descendantsOfType('block');
330
+ for (const resource of resources) {
331
+ const labels = resource.children.filter(child => child.type === 'identifier');
332
+ if (labels.length >= 2) {
333
+ const resourceType = labels[0]?.text || 'unknown';
334
+ const resourceName = labels[1]?.text || 'unnamed';
335
+ // Determine provider
336
+ let provider = 'aws';
337
+ if (resourceType.startsWith('google_'))
338
+ provider = 'gcp';
339
+ else if (resourceType.startsWith('azurerm_'))
340
+ provider = 'azure';
341
+ else if (resourceType.startsWith('kubernetes_'))
342
+ provider = 'kubernetes';
343
+ const securityRisks = this.analyzeTerraformSecurity(resource);
344
+ result.infraStructure.push({
345
+ resourceType,
346
+ name: resourceName,
347
+ provider,
348
+ configuration: {},
349
+ securityRisks,
350
+ location: { line: resource.startPosition.row + 1, column: resource.startPosition.column },
351
+ });
352
+ }
353
+ }
354
+ }
355
+ /**
356
+ * Dockerfile analysis for container security
357
+ */
358
+ async analyzeDockerfile(_node, lines, result) {
359
+ // Analyze each instruction
360
+ for (const line of lines) {
361
+ const trimmed = line.trim();
362
+ if (trimmed.startsWith('USER ')) {
363
+ const user = trimmed.substring(5).trim();
364
+ if (user === 'root') {
365
+ result.securityIssues.push({
366
+ type: 'privilege_escalation',
367
+ severity: 'high',
368
+ message: 'Running as root user in container',
369
+ location: { line: lines.indexOf(line) + 1, column: 0 },
370
+ suggestion: 'Create and use a non-root user',
371
+ });
372
+ }
373
+ }
374
+ }
375
+ }
376
+ /**
377
+ * Bash script analysis
378
+ */
379
+ async analyzeBash(node, _lines, result) {
380
+ // Find variable assignments and command substitutions
381
+ const assignments = node.descendantsOfType('variable_assignment');
382
+ for (const assignment of assignments) {
383
+ const nameNode = assignment.childForFieldName('name');
384
+ const valueNode = assignment.childForFieldName('value');
385
+ if (nameNode && valueNode) {
386
+ result.variables.push({
387
+ name: nameNode.text,
388
+ type: 'var',
389
+ value: valueNode.text,
390
+ location: {
391
+ line: assignment.startPosition.row + 1,
392
+ column: assignment.startPosition.column,
393
+ },
394
+ isSensitive: this.isSensitiveVariable(nameNode.text, valueNode.text),
395
+ scope: 'script',
396
+ });
397
+ }
398
+ }
399
+ }
400
+ /**
401
+ * JSON analysis for configuration files
402
+ */
403
+ async analyzeJSON(node, _lines, result) {
404
+ // Analyze JSON objects for secrets
405
+ const pairs = node.descendantsOfType('pair');
406
+ for (const pair of pairs) {
407
+ const keyNode = pair.children[0];
408
+ const valueNode = pair.children[2];
409
+ if (keyNode && valueNode && valueNode.type === 'string') {
410
+ const key = keyNode.text.replace(/['"]/g, '');
411
+ const value = valueNode.text.replace(/['"]/g, '');
412
+ if (this.isSensitiveVariable(key, value)) {
413
+ result.secrets.push({
414
+ type: this.classifySecret(key, value),
415
+ value: value,
416
+ location: { line: pair.startPosition.row + 1, column: pair.startPosition.column },
417
+ confidence: 0.8,
418
+ context: `JSON key: ${key}`,
419
+ });
420
+ }
421
+ }
422
+ }
423
+ }
424
+ /**
425
+ * Universal secret detection across all languages
426
+ */
427
+ async analyzeSecrets(node, _lines, result) {
428
+ // Find all string literals and analyze them
429
+ const strings = node
430
+ .descendantsOfType('string')
431
+ .concat(node.descendantsOfType('string_literal'));
432
+ for (const stringNode of strings) {
433
+ const text = stringNode.text.replace(/['"]/g, '');
434
+ const secretType = this.detectSecretPattern(text);
435
+ if (secretType) {
436
+ result.secrets.push({
437
+ type: secretType,
438
+ value: text,
439
+ location: {
440
+ line: stringNode.startPosition.row + 1,
441
+ column: stringNode.startPosition.column,
442
+ },
443
+ confidence: 0.7,
444
+ context: 'String literal',
445
+ });
446
+ }
447
+ }
448
+ }
449
+ /**
450
+ * Fallback analysis using regex when tree-sitter fails
451
+ */
452
+ fallbackAnalysis(_filePath, content, language) {
453
+ const lines = content.split('\n');
454
+ const result = {
455
+ language,
456
+ hasSecrets: false,
457
+ secrets: [],
458
+ imports: [],
459
+ functions: [],
460
+ variables: [],
461
+ infraStructure: [],
462
+ securityIssues: [],
463
+ architecturalViolations: [],
464
+ };
465
+ // Basic regex-based secret detection
466
+ const secretPatterns = [
467
+ { pattern: /(?:api[_-]?key|apikey)[:=]\s*['""]([^'""]+)['""]?/i, type: 'api_key' },
468
+ { pattern: /(?:password|pwd|pass)[:=]\s*['""]([^'""]+)['""]?/i, type: 'password' },
469
+ { pattern: /(?:token|auth)[:=]\s*['""]([^'""]+)['""]?/i, type: 'token' },
470
+ {
471
+ pattern: /(?:secret|private[_-]?key)[:=]\s*['""]([^'""]+)['""]?/i,
472
+ type: 'private_key',
473
+ },
474
+ ];
475
+ lines.forEach((line, index) => {
476
+ secretPatterns.forEach(({ pattern, type }) => {
477
+ const match = line.match(pattern);
478
+ if (match && match[1] && match[1].length > 8) {
479
+ result.secrets.push({
480
+ type,
481
+ value: match[1],
482
+ location: { line: index + 1, column: match.index || 0 },
483
+ confidence: 0.6,
484
+ context: line.trim(),
485
+ });
486
+ }
487
+ });
488
+ });
489
+ result.hasSecrets = result.secrets.length > 0;
490
+ return result;
491
+ }
492
+ // Helper methods
493
+ checkDangerousImport(importText, language) {
494
+ const dangerousModules = {
495
+ python: ['eval', 'exec', 'subprocess', 'os.system'],
496
+ javascript: ['eval', 'child_process', 'vm'],
497
+ };
498
+ const dangerous = dangerousModules[language] || [];
499
+ return dangerous.some(module => importText.includes(module));
500
+ }
501
+ extractPythonParameters(funcNode) {
502
+ const paramsNode = funcNode.childForFieldName('parameters');
503
+ if (!paramsNode)
504
+ return [];
505
+ return paramsNode.namedChildren
506
+ .filter(child => child.type === 'identifier')
507
+ .map(child => child.text);
508
+ }
509
+ extractJSParameters(funcNode) {
510
+ const paramsNode = funcNode.childForFieldName('parameters');
511
+ if (!paramsNode)
512
+ return [];
513
+ return paramsNode.namedChildren
514
+ .filter(child => child.type === 'identifier')
515
+ .map(child => child.text);
516
+ }
517
+ calculateComplexity(node) {
518
+ // Simple cyclomatic complexity calculation
519
+ const complexityNodes = ['if_statement', 'while_statement', 'for_statement', 'try_statement'];
520
+ let complexity = 1;
521
+ const walk = (n) => {
522
+ if (complexityNodes.includes(n.type)) {
523
+ complexity++;
524
+ }
525
+ n.children.forEach(child => walk(child));
526
+ };
527
+ walk(node);
528
+ return complexity;
529
+ }
530
+ isSecuritySensitive(name) {
531
+ const sensitiveNames = [
532
+ 'auth',
533
+ 'login',
534
+ 'password',
535
+ 'token',
536
+ 'key',
537
+ 'secret',
538
+ 'decrypt',
539
+ 'hash',
540
+ ];
541
+ return sensitiveNames.some(sensitive => name.toLowerCase().includes(sensitive));
542
+ }
543
+ isSensitiveVariable(name, value) {
544
+ const sensitiveKeys = ['password', 'secret', 'key', 'token', 'auth', 'private', 'credential'];
545
+ const nameCheck = sensitiveKeys.some(key => name.toLowerCase().includes(key));
546
+ const valueCheck = Boolean(value && value.length > 16 && /^[A-Za-z0-9+/=]+$/.test(value));
547
+ return nameCheck || valueCheck;
548
+ }
549
+ classifySecret(key, _value) {
550
+ if (key.toLowerCase().includes('password'))
551
+ return 'password';
552
+ if (key.toLowerCase().includes('token'))
553
+ return 'token';
554
+ if (key.toLowerCase().includes('key'))
555
+ return 'api_key';
556
+ if (key.toLowerCase().includes('private'))
557
+ return 'private_key';
558
+ return 'credential';
559
+ }
560
+ detectSecretPattern(text) {
561
+ // AWS Access Key
562
+ if (/^AKIA[0-9A-Z]{16}$/.test(text))
563
+ return 'api_key';
564
+ // Generic API key patterns
565
+ if (/^[A-Za-z0-9]{32,}$/.test(text) && text.length >= 32)
566
+ return 'api_key';
567
+ // JWT Token
568
+ if (/^eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/]*$/.test(text))
569
+ return 'token';
570
+ return null;
571
+ }
572
+ isAnsibleFile(filename, content) {
573
+ return (filename.includes('playbook') ||
574
+ filename.includes('ansible') ||
575
+ content.includes('hosts:') ||
576
+ content.includes('tasks:') ||
577
+ content.includes('roles:'));
578
+ }
579
+ isKubernetesFile(filename, content) {
580
+ return (filename.includes('k8s') ||
581
+ filename.includes('kubernetes') ||
582
+ content.includes('apiVersion:') ||
583
+ content.includes('kind:'));
584
+ }
585
+ isDockerComposeFile(filename, content) {
586
+ return (filename.includes('docker-compose') ||
587
+ (content.includes('version:') && content.includes('services:')));
588
+ }
589
+ async analyzeAnsibleYAML(_node, lines, result) {
590
+ const content = lines.join('\n');
591
+ // Detect Ansible tasks and roles
592
+ if (content.includes('tasks:')) {
593
+ const taskMatches = content.match(/- name:\s*(.+)/g) || [];
594
+ taskMatches.forEach(match => {
595
+ const taskName = match.replace(/- name:\s*/, '').trim();
596
+ result.functions.push({
597
+ name: taskName,
598
+ type: 'task',
599
+ parameters: [],
600
+ location: { line: this.findLineNumber(lines, match), column: 0 },
601
+ complexity: 1,
602
+ securitySensitive: this.isSecuritySensitiveTask(taskName),
603
+ });
604
+ });
605
+ }
606
+ // Detect role imports
607
+ const roleMatches = content.match(/roles?:\s*\n([\s\S]*?)(?=\n\w|$)/g) || [];
608
+ roleMatches.forEach(roleBlock => {
609
+ const roles = roleBlock.match(/- ([\w.-]+)/g) || [];
610
+ roles.forEach(role => {
611
+ const roleName = role.replace(/- /, '');
612
+ result.imports.push({
613
+ module: roleName,
614
+ type: 'role',
615
+ location: { line: this.findLineNumber(lines, role), column: 0 },
616
+ isExternal: !roleName.startsWith('./'),
617
+ isDangerous: this.isDangerousAnsibleRole(roleName),
618
+ });
619
+ });
620
+ });
621
+ // Check for security-sensitive variables
622
+ const varMatches = content.match(/\b\w*(?:password|secret|key|token)\w*:\s*["']?([^"'\n]+)["']?/gi) || [];
623
+ varMatches.forEach(varMatch => {
624
+ const [fullMatch, value] = varMatch.match(/([\w_]+):\s*["']?([^"'\n]+)["']?/) || [];
625
+ if (fullMatch && value) {
626
+ result.secrets.push({
627
+ type: 'credential',
628
+ value: value,
629
+ location: { line: this.findLineNumber(lines, fullMatch), column: 0 },
630
+ confidence: 0.7,
631
+ context: 'Ansible variable',
632
+ });
633
+ }
634
+ });
635
+ }
636
+ async analyzeKubernetesYAML(_node, lines, result) {
637
+ const content = lines.join('\n');
638
+ // Extract Kubernetes resources
639
+ const resourceMatches = content.match(/kind:\s*(\w+)/g) || [];
640
+ const apiVersionMatches = content.match(/apiVersion:\s*([\w/]+)/g) || [];
641
+ const nameMatches = content.match(/name:\s*([\w.-]+)/g) || [];
642
+ if (resourceMatches.length > 0) {
643
+ resourceMatches.forEach((kindMatch, index) => {
644
+ const kind = kindMatch.replace(/kind:\s*/, '');
645
+ const apiVersion = apiVersionMatches[index]?.replace(/apiVersion:\s*/, '') || 'v1';
646
+ const name = nameMatches[index]?.replace(/name:\s*/, '') || 'unnamed';
647
+ const securityRisks = this.analyzeKubernetesSecurityRisks(content, kind);
648
+ result.infraStructure.push({
649
+ resourceType: kind.toLowerCase(),
650
+ name: name,
651
+ provider: 'kubernetes',
652
+ configuration: { apiVersion, kind },
653
+ securityRisks,
654
+ location: { line: this.findLineNumber(lines, kindMatch), column: 0 },
655
+ });
656
+ });
657
+ }
658
+ // Check for security contexts and privileged containers
659
+ if (content.includes('privileged: true')) {
660
+ result.securityIssues.push({
661
+ type: 'privilege_escalation',
662
+ severity: 'high',
663
+ message: 'Container running in privileged mode',
664
+ location: { line: this.findLineNumber(lines, 'privileged: true'), column: 0 },
665
+ suggestion: 'Remove privileged: true and use specific capabilities instead',
666
+ });
667
+ }
668
+ // Check for missing resource limits
669
+ if (content.includes('containers:') && !content.includes('resources:')) {
670
+ result.securityIssues.push({
671
+ type: 'insecure_config',
672
+ severity: 'medium',
673
+ message: 'Container missing resource limits',
674
+ location: { line: this.findLineNumber(lines, 'containers:'), column: 0 },
675
+ suggestion: 'Add resource requests and limits to prevent resource exhaustion',
676
+ });
677
+ }
678
+ // Detect secrets in environment variables
679
+ const envMatches = content.match(/env:\s*\n([\s\S]*?)(?=\n\s*\w|$)/g) || [];
680
+ envMatches.forEach(envBlock => {
681
+ const secretRefs = envBlock.match(/valueFrom:\s*\n\s*secretKeyRef:/g) || [];
682
+ if (secretRefs.length === 0 && envBlock.includes('value:')) {
683
+ // Direct environment values might contain secrets
684
+ const directValues = envBlock.match(/- name:\s*(\w*(?:PASSWORD|SECRET|KEY|TOKEN)\w*)\s*\n\s*value:\s*([^\n]+)/gi) || [];
685
+ directValues.forEach(match => {
686
+ const [, envName, envValue] = match.match(/- name:\s*(\w+)\s*\n\s*value:\s*([^\n]+)/i) || [];
687
+ if (envName && envValue) {
688
+ result.secrets.push({
689
+ type: 'credential',
690
+ value: envValue,
691
+ location: { line: this.findLineNumber(lines, match), column: 0 },
692
+ confidence: 0.8,
693
+ context: `Kubernetes env var: ${envName}`,
694
+ });
695
+ }
696
+ });
697
+ }
698
+ });
699
+ }
700
+ async analyzeDockerComposeYAML(_node, lines, result) {
701
+ const content = lines.join('\n');
702
+ // Extract services
703
+ const serviceMatches = content.match(/^\s{2}(\w[\w.-]*):$/gm) || [];
704
+ serviceMatches.forEach(serviceMatch => {
705
+ const serviceName = serviceMatch.replace(/^\s{2}/, '').replace(/:$/, '');
706
+ result.infraStructure.push({
707
+ resourceType: 'docker_service',
708
+ name: serviceName,
709
+ provider: 'docker',
710
+ configuration: {},
711
+ securityRisks: this.analyzeDockerComposeSecurityRisks(content, serviceName),
712
+ location: { line: this.findLineNumber(lines, serviceMatch), column: 0 },
713
+ });
714
+ });
715
+ // Check for exposed ports
716
+ const portMatches = content.match(/ports:\s*\n([\s\S]*?)(?=\n\s*\w|$)/g) || [];
717
+ portMatches.forEach(portBlock => {
718
+ if (portBlock.includes('"80:') || portBlock.includes('"443:')) {
719
+ const webPorts = portBlock.match(/"(80|443):[^"]+"/g) || [];
720
+ webPorts.forEach(port => {
721
+ result.securityIssues.push({
722
+ type: 'insecure_config',
723
+ severity: 'medium',
724
+ message: `Web port ${port} exposed without TLS configuration`,
725
+ location: { line: this.findLineNumber(lines, port), column: 0 },
726
+ suggestion: 'Ensure proper TLS termination and security headers',
727
+ });
728
+ });
729
+ }
730
+ });
731
+ // Check for environment variables with secrets
732
+ const envMatches = content.match(/environment:\s*\n([\s\S]*?)(?=\n\s*\w|$)/g) || [];
733
+ envMatches.forEach(envBlock => {
734
+ const secretVars = envBlock.match(/\s*-?\s*(\w*(?:PASSWORD|SECRET|KEY|TOKEN|API_KEY)\w*)\s*[:=]\s*([^\n]+)/gi) || [];
735
+ secretVars.forEach(secretVar => {
736
+ const [, varName, varValue] = secretVar.match(/\s*-?\s*(\w+)\s*[:=]\s*([^\n]+)/i) || [];
737
+ if (varName && varValue && !varValue.includes('${')) {
738
+ result.secrets.push({
739
+ type: 'credential',
740
+ value: varValue,
741
+ location: { line: this.findLineNumber(lines, secretVar), column: 0 },
742
+ confidence: 0.8,
743
+ context: `Docker Compose env var: ${varName}`,
744
+ });
745
+ }
746
+ });
747
+ });
748
+ // Check for privileged containers
749
+ if (content.includes('privileged: true')) {
750
+ result.securityIssues.push({
751
+ type: 'privilege_escalation',
752
+ severity: 'high',
753
+ message: 'Container running in privileged mode',
754
+ location: { line: this.findLineNumber(lines, 'privileged: true'), column: 0 },
755
+ suggestion: 'Remove privileged mode and use specific capabilities instead',
756
+ });
757
+ }
758
+ }
759
+ analyzeTerraformSecurity(resource) {
760
+ const risks = [];
761
+ // Check for common security issues in Terraform
762
+ const resourceText = resource.text.toLowerCase();
763
+ if (resourceText.includes('0.0.0.0/0')) {
764
+ risks.push('Open to all IP addresses');
765
+ }
766
+ if (resourceText.includes('port = 22') && resourceText.includes('0.0.0.0/0')) {
767
+ risks.push('SSH port open to internet');
768
+ }
769
+ return risks;
770
+ }
771
+ // Helper methods for the enhanced YAML analysis
772
+ findLineNumber(lines, searchText) {
773
+ for (let i = 0; i < lines.length; i++) {
774
+ if (lines[i]?.includes(searchText)) {
775
+ return i + 1;
776
+ }
777
+ }
778
+ return 1;
779
+ }
780
+ isSecuritySensitiveTask(taskName) {
781
+ const sensitiveKeywords = [
782
+ 'password',
783
+ 'secret',
784
+ 'key',
785
+ 'token',
786
+ 'auth',
787
+ 'login',
788
+ 'credential',
789
+ 'sudo',
790
+ 'become',
791
+ 'privilege',
792
+ 'root',
793
+ 'admin',
794
+ 'ssh',
795
+ 'ssl',
796
+ 'tls',
797
+ ];
798
+ const lowerTaskName = taskName.toLowerCase();
799
+ return sensitiveKeywords.some(keyword => lowerTaskName.includes(keyword));
800
+ }
801
+ isDangerousAnsibleRole(roleName) {
802
+ const dangerousRoles = [
803
+ 'shell',
804
+ 'command',
805
+ 'raw',
806
+ 'script',
807
+ 'sudo',
808
+ 'become',
809
+ 'privilege',
810
+ 'firewall',
811
+ 'iptables',
812
+ 'selinux',
813
+ 'apparmor',
814
+ ];
815
+ const lowerRoleName = roleName.toLowerCase();
816
+ return dangerousRoles.some(dangerous => lowerRoleName.includes(dangerous));
817
+ }
818
+ analyzeKubernetesSecurityRisks(content, kind) {
819
+ const risks = [];
820
+ const lowerContent = content.toLowerCase();
821
+ // Check for privileged containers
822
+ if (lowerContent.includes('privileged: true')) {
823
+ risks.push('Privileged container detected');
824
+ }
825
+ // Check for host network
826
+ if (lowerContent.includes('hostnetwork: true')) {
827
+ risks.push('Host network access enabled');
828
+ }
829
+ // Check for host PID
830
+ if (lowerContent.includes('hostpid: true')) {
831
+ risks.push('Host PID namespace access enabled');
832
+ }
833
+ // Check for missing security context
834
+ if (kind.toLowerCase() === 'deployment' && !lowerContent.includes('securitycontext')) {
835
+ risks.push('Missing security context configuration');
836
+ }
837
+ // Check for root user
838
+ if (lowerContent.includes('runasuser: 0')) {
839
+ risks.push('Container running as root user');
840
+ }
841
+ // Check for missing resource limits
842
+ if (lowerContent.includes('containers:') && !lowerContent.includes('resources:')) {
843
+ risks.push('Missing resource limits');
844
+ }
845
+ return risks;
846
+ }
847
+ analyzeDockerComposeSecurityRisks(content, serviceName) {
848
+ const risks = [];
849
+ // Extract service-specific content
850
+ const serviceRegex = new RegExp(`\\s{2}${serviceName}:\\s*\\n([\\s\\S]*?)(?=\\n\\s{2}\\w|$)`, 'i');
851
+ const serviceMatch = content.match(serviceRegex);
852
+ const serviceContent = serviceMatch?.[1]?.toLowerCase() || '';
853
+ // Check for privileged mode
854
+ if (serviceContent.includes('privileged: true')) {
855
+ risks.push('Service running in privileged mode');
856
+ }
857
+ // Check for host network
858
+ if (serviceContent.includes('network_mode: host')) {
859
+ risks.push('Service using host network');
860
+ }
861
+ // Check for volume mounts to sensitive paths
862
+ const sensitiveVolumes = ['/etc', '/var/run/docker.sock', '/proc', '/sys'];
863
+ sensitiveVolumes.forEach(path => {
864
+ if (serviceContent.includes(`${path}:`)) {
865
+ risks.push(`Mounting sensitive host path: ${path}`);
866
+ }
867
+ });
868
+ // Check for exposed ports without proper configuration
869
+ if (serviceContent.includes('ports:') && serviceContent.includes('"80:')) {
870
+ risks.push('HTTP port exposed without TLS');
871
+ }
872
+ // Check for missing restart policy
873
+ if (!serviceContent.includes('restart:')) {
874
+ risks.push('Missing restart policy');
875
+ }
876
+ return risks;
877
+ }
878
+ }
879
+ // Factory function for easy usage
880
+ export function createTreeSitterAnalyzer() {
881
+ return new TreeSitterAnalyzer();
882
+ }
883
+ // Export default analyzer instance
884
+ export const analyzer = new TreeSitterAnalyzer();
885
+ //# sourceMappingURL=tree-sitter-analyzer.js.map