@datahogo/core 0.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 (153) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +17 -0
  3. package/dist/engines/config.d.ts +3 -0
  4. package/dist/engines/config.d.ts.map +1 -0
  5. package/dist/engines/config.js +433 -0
  6. package/dist/engines/config.js.map +1 -0
  7. package/dist/engines/dast.d.ts +3 -0
  8. package/dist/engines/dast.d.ts.map +1 -0
  9. package/dist/engines/dast.js +167 -0
  10. package/dist/engines/dast.js.map +1 -0
  11. package/dist/engines/db-rules.d.ts +3 -0
  12. package/dist/engines/db-rules.d.ts.map +1 -0
  13. package/dist/engines/db-rules.js +166 -0
  14. package/dist/engines/db-rules.js.map +1 -0
  15. package/dist/engines/dependencies.d.ts +3 -0
  16. package/dist/engines/dependencies.d.ts.map +1 -0
  17. package/dist/engines/dependencies.js +167 -0
  18. package/dist/engines/dependencies.js.map +1 -0
  19. package/dist/engines/github-actions.d.ts +3 -0
  20. package/dist/engines/github-actions.d.ts.map +1 -0
  21. package/dist/engines/github-actions.js +215 -0
  22. package/dist/engines/github-actions.js.map +1 -0
  23. package/dist/engines/gitleaks.d.ts +3 -0
  24. package/dist/engines/gitleaks.d.ts.map +1 -0
  25. package/dist/engines/gitleaks.js +107 -0
  26. package/dist/engines/gitleaks.js.map +1 -0
  27. package/dist/engines/npm-audit.d.ts +3 -0
  28. package/dist/engines/npm-audit.d.ts.map +1 -0
  29. package/dist/engines/npm-audit.js +113 -0
  30. package/dist/engines/npm-audit.js.map +1 -0
  31. package/dist/engines/patterns.d.ts +3 -0
  32. package/dist/engines/patterns.d.ts.map +1 -0
  33. package/dist/engines/patterns.js +1330 -0
  34. package/dist/engines/patterns.js.map +1 -0
  35. package/dist/engines/secrets.d.ts +4 -0
  36. package/dist/engines/secrets.d.ts.map +1 -0
  37. package/dist/engines/secrets.js +260 -0
  38. package/dist/engines/secrets.js.map +1 -0
  39. package/dist/engines/semgrep.d.ts +3 -0
  40. package/dist/engines/semgrep.d.ts.map +1 -0
  41. package/dist/engines/semgrep.js +173 -0
  42. package/dist/engines/semgrep.js.map +1 -0
  43. package/dist/engines/types.d.ts +30 -0
  44. package/dist/engines/types.d.ts.map +1 -0
  45. package/dist/engines/types.js +3 -0
  46. package/dist/engines/types.js.map +1 -0
  47. package/dist/engines/url-scanner.d.ts +3 -0
  48. package/dist/engines/url-scanner.d.ts.map +1 -0
  49. package/dist/engines/url-scanner.js +469 -0
  50. package/dist/engines/url-scanner.js.map +1 -0
  51. package/dist/index.d.ts +8 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/orchestrator.d.ts +32 -0
  56. package/dist/orchestrator.d.ts.map +1 -0
  57. package/dist/orchestrator.js +237 -0
  58. package/dist/orchestrator.js.map +1 -0
  59. package/dist/rules/.gitkeep +0 -0
  60. package/dist/rules/ai-llm-security.yaml +199 -0
  61. package/dist/rules/api-security.yaml +489 -0
  62. package/dist/rules/auth-patterns.yaml +406 -0
  63. package/dist/rules/crypto-patterns.yaml +227 -0
  64. package/dist/rules/database-cloud-security.yaml +169 -0
  65. package/dist/rules/general-security.yaml +588 -0
  66. package/dist/rules/injection-patterns.yaml +318 -0
  67. package/dist/rules/nextjs-security.yaml +532 -0
  68. package/dist/rules/node-security.yaml +380 -0
  69. package/dist/rules/rules/.gitkeep +0 -0
  70. package/dist/rules/rules/ai-llm-security.yaml +199 -0
  71. package/dist/rules/rules/api-security.yaml +489 -0
  72. package/dist/rules/rules/auth-patterns.yaml +406 -0
  73. package/dist/rules/rules/crypto-patterns.yaml +227 -0
  74. package/dist/rules/rules/database-cloud-security.yaml +169 -0
  75. package/dist/rules/rules/general-security.yaml +588 -0
  76. package/dist/rules/rules/injection-patterns.yaml +318 -0
  77. package/dist/rules/rules/nextjs-security.yaml +532 -0
  78. package/dist/rules/rules/node-security.yaml +380 -0
  79. package/dist/rules/rules/supabase-security.yaml +387 -0
  80. package/dist/rules/supabase-security.yaml +387 -0
  81. package/dist/scanning/agents/csharp-agent.d.ts +12 -0
  82. package/dist/scanning/agents/csharp-agent.d.ts.map +1 -0
  83. package/dist/scanning/agents/csharp-agent.js +592 -0
  84. package/dist/scanning/agents/csharp-agent.js.map +1 -0
  85. package/dist/scanning/agents/go-agent.d.ts +14 -0
  86. package/dist/scanning/agents/go-agent.d.ts.map +1 -0
  87. package/dist/scanning/agents/go-agent.js +641 -0
  88. package/dist/scanning/agents/go-agent.js.map +1 -0
  89. package/dist/scanning/agents/java-agent.d.ts +8 -0
  90. package/dist/scanning/agents/java-agent.d.ts.map +1 -0
  91. package/dist/scanning/agents/java-agent.js +807 -0
  92. package/dist/scanning/agents/java-agent.js.map +1 -0
  93. package/dist/scanning/agents/javascript-agent.d.ts +8 -0
  94. package/dist/scanning/agents/javascript-agent.d.ts.map +1 -0
  95. package/dist/scanning/agents/javascript-agent.js +77 -0
  96. package/dist/scanning/agents/javascript-agent.js.map +1 -0
  97. package/dist/scanning/agents/mobile-agent.d.ts +8 -0
  98. package/dist/scanning/agents/mobile-agent.d.ts.map +1 -0
  99. package/dist/scanning/agents/mobile-agent.js +916 -0
  100. package/dist/scanning/agents/mobile-agent.js.map +1 -0
  101. package/dist/scanning/agents/php-agent.d.ts +8 -0
  102. package/dist/scanning/agents/php-agent.d.ts.map +1 -0
  103. package/dist/scanning/agents/php-agent.js +679 -0
  104. package/dist/scanning/agents/php-agent.js.map +1 -0
  105. package/dist/scanning/agents/python-agent.d.ts +8 -0
  106. package/dist/scanning/agents/python-agent.d.ts.map +1 -0
  107. package/dist/scanning/agents/python-agent.js +701 -0
  108. package/dist/scanning/agents/python-agent.js.map +1 -0
  109. package/dist/scanning/agents/supabase-agent.d.ts +8 -0
  110. package/dist/scanning/agents/supabase-agent.d.ts.map +1 -0
  111. package/dist/scanning/agents/supabase-agent.js +484 -0
  112. package/dist/scanning/agents/supabase-agent.js.map +1 -0
  113. package/dist/scanning/orchestrator.d.ts +29 -0
  114. package/dist/scanning/orchestrator.d.ts.map +1 -0
  115. package/dist/scanning/orchestrator.js +186 -0
  116. package/dist/scanning/orchestrator.js.map +1 -0
  117. package/dist/scanning/tech-detector.d.ts +12 -0
  118. package/dist/scanning/tech-detector.d.ts.map +1 -0
  119. package/dist/scanning/tech-detector.js +252 -0
  120. package/dist/scanning/tech-detector.js.map +1 -0
  121. package/dist/scanning/types.d.ts +87 -0
  122. package/dist/scanning/types.d.ts.map +1 -0
  123. package/dist/scanning/types.js +5 -0
  124. package/dist/scanning/types.js.map +1 -0
  125. package/dist/utils/child-process.d.ts +2 -0
  126. package/dist/utils/child-process.d.ts.map +1 -0
  127. package/dist/utils/child-process.js +4 -0
  128. package/dist/utils/child-process.js.map +1 -0
  129. package/dist/utils/context-classifier.d.ts +11 -0
  130. package/dist/utils/context-classifier.d.ts.map +1 -0
  131. package/dist/utils/context-classifier.js +79 -0
  132. package/dist/utils/context-classifier.js.map +1 -0
  133. package/dist/utils/exec.d.ts +18 -0
  134. package/dist/utils/exec.d.ts.map +1 -0
  135. package/dist/utils/exec.js +51 -0
  136. package/dist/utils/exec.js.map +1 -0
  137. package/dist/utils/file-filter.d.ts +4 -0
  138. package/dist/utils/file-filter.d.ts.map +1 -0
  139. package/dist/utils/file-filter.js +68 -0
  140. package/dist/utils/file-filter.js.map +1 -0
  141. package/dist/utils/fs.d.ts +2 -0
  142. package/dist/utils/fs.d.ts.map +1 -0
  143. package/dist/utils/fs.js +5 -0
  144. package/dist/utils/fs.js.map +1 -0
  145. package/dist/utils/logger.d.ts +12 -0
  146. package/dist/utils/logger.d.ts.map +1 -0
  147. package/dist/utils/logger.js +27 -0
  148. package/dist/utils/logger.js.map +1 -0
  149. package/dist/utils/post-processor.d.ts +10 -0
  150. package/dist/utils/post-processor.d.ts.map +1 -0
  151. package/dist/utils/post-processor.js +183 -0
  152. package/dist/utils/post-processor.js.map +1 -0
  153. package/package.json +44 -0
@@ -0,0 +1,186 @@
1
+ // Multi-technology scan orchestrator.
2
+ // Uses TechDetector to identify technologies, instantiates the relevant
3
+ // ScanAgents, runs them in parallel, and aggregates into a ScanReport.
4
+ import { detectTechnologies } from "./tech-detector.js";
5
+ import { PythonScanAgent } from "./agents/python-agent.js";
6
+ import { JavaScriptScanAgent } from "./agents/javascript-agent.js";
7
+ import { GoScanAgent } from "./agents/go-agent.js";
8
+ import { JavaScanAgent } from "./agents/java-agent.js";
9
+ import { PHPScanAgent } from "./agents/php-agent.js";
10
+ import { CSharpScanAgent } from "./agents/csharp-agent.js";
11
+ import { MobileScanAgent } from "./agents/mobile-agent.js";
12
+ import { SupabaseScanAgent } from "./agents/supabase-agent.js";
13
+ const SEVERITY_PENALTY = {
14
+ CRITICAL: 15,
15
+ HIGH: 10,
16
+ MEDIUM: 5,
17
+ LOW: 2,
18
+ INFO: 0,
19
+ };
20
+ const AGENT_TIMEOUT_MS = 90_000; // 90s per agent
21
+ /**
22
+ * Registry of all available scan agents.
23
+ * Agents register themselves here; the orchestrator picks which ones to run.
24
+ */
25
+ const agentRegistry = [];
26
+ /** Register a scan agent. Called by each agent module on import. */
27
+ export function registerAgent(agent) {
28
+ agentRegistry.push(agent);
29
+ }
30
+ /** Get all registered agents (for testing). */
31
+ export function getRegisteredAgents() {
32
+ return agentRegistry;
33
+ }
34
+ /** Clear registry (for testing). */
35
+ export function clearAgentRegistry() {
36
+ agentRegistry.length = 0;
37
+ }
38
+ // Register built-in agents
39
+ registerAgent(new PythonScanAgent());
40
+ registerAgent(new JavaScriptScanAgent());
41
+ registerAgent(new GoScanAgent());
42
+ registerAgent(new JavaScanAgent());
43
+ registerAgent(new PHPScanAgent());
44
+ registerAgent(new CSharpScanAgent());
45
+ registerAgent(new MobileScanAgent());
46
+ registerAgent(new SupabaseScanAgent());
47
+ /**
48
+ * Run a full multi-technology scan.
49
+ *
50
+ * 1. Detect technologies in the repo
51
+ * 2. Filter agents to only those whose technologies match
52
+ * 3. Run matching agents in parallel (with timeout)
53
+ * 4. Deduplicate and aggregate results into a ScanReport
54
+ */
55
+ export async function runMultiTechScan(files, options = {}) {
56
+ const startTime = Date.now();
57
+ const detection = detectTechnologies(files);
58
+ const excluded = options.exclude ?? [];
59
+ // Find agents that support at least one detected technology
60
+ const matchingAgents = agentRegistry.filter((agent) => {
61
+ const meta = agent.getMetadata();
62
+ if (excluded.includes(meta.name))
63
+ return false;
64
+ return meta.technologies.some((tech) => detection.technologies.includes(tech));
65
+ });
66
+ const matchedNames = matchingAgents.map((a) => a.getMetadata().name);
67
+ // Run detect() on matching agents to confirm (agents may have stricter checks)
68
+ const confirmedAgents = [];
69
+ await Promise.all(matchingAgents.map(async (agent) => {
70
+ try {
71
+ const detected = await agent.detect(files);
72
+ if (detected)
73
+ confirmedAgents.push(agent);
74
+ }
75
+ catch {
76
+ // If detect fails, skip this agent
77
+ }
78
+ }));
79
+ const confirmedNames = confirmedAgents.map((a) => a.getMetadata().name);
80
+ // Run scan() on confirmed agents in parallel with timeout
81
+ const agentResults = await Promise.all(confirmedAgents.map((agent) => runAgentWithTimeout(agent, files)));
82
+ // Build agent logs by diffing getChecks() against findings
83
+ const agentLogs = agentResults.map((ar) => {
84
+ const agent = confirmedAgents.find((a) => a.getMetadata().name === ar.agentName);
85
+ const meta = agent?.getMetadata();
86
+ const checks = agent?.getChecks?.() ?? [];
87
+ const checkResults = checks.map((check) => {
88
+ const count = ar.results.filter((r) => r.checkId === check.id).length;
89
+ return {
90
+ checkId: check.id,
91
+ status: count > 0 ? "fail" : "pass",
92
+ findingCount: count,
93
+ };
94
+ });
95
+ const passed = checkResults.filter((c) => c.status === "pass").length;
96
+ const failed = checkResults.filter((c) => c.status === "fail").length;
97
+ return {
98
+ agentName: ar.agentName,
99
+ agentVersion: meta?.version ?? "unknown",
100
+ technologies: meta?.technologies ?? [],
101
+ status: ar.error
102
+ ? ar.error.includes("timed out") ? "timeout" : "error"
103
+ : "completed",
104
+ durationMs: ar.durationMs,
105
+ checkResults,
106
+ totalChecks: checkResults.length,
107
+ passed,
108
+ failed,
109
+ error: ar.error,
110
+ };
111
+ });
112
+ const scanLog = {
113
+ technologiesDetected: detection.technologies,
114
+ technologyDetails: Object.fromEntries(detection.details),
115
+ agentsMatched: matchedNames,
116
+ agentsConfirmed: confirmedNames,
117
+ agentLogs,
118
+ totalDurationMs: Date.now() - startTime,
119
+ summary: {
120
+ totalChecks: agentLogs.reduce((s, a) => s + a.totalChecks, 0),
121
+ passed: agentLogs.reduce((s, a) => s + a.passed, 0),
122
+ failed: agentLogs.reduce((s, a) => s + a.failed, 0),
123
+ },
124
+ };
125
+ // Aggregate all results
126
+ const allResults = agentResults.flatMap((ar) => ar.results);
127
+ const deduplicated = deduplicateResults(allResults);
128
+ const score = calculateScore(deduplicated);
129
+ return {
130
+ score,
131
+ results: deduplicated,
132
+ techsDetected: detection.technologies,
133
+ timestamp: new Date().toISOString(),
134
+ agentResults,
135
+ scanLog,
136
+ };
137
+ }
138
+ async function runAgentWithTimeout(agent, files) {
139
+ const meta = agent.getMetadata();
140
+ const start = Date.now();
141
+ try {
142
+ const results = await Promise.race([
143
+ agent.scan(files),
144
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Agent ${meta.name} timed out after ${AGENT_TIMEOUT_MS}ms`)), AGENT_TIMEOUT_MS)),
145
+ ]);
146
+ return {
147
+ agentName: meta.name,
148
+ results,
149
+ durationMs: Date.now() - start,
150
+ };
151
+ }
152
+ catch (error) {
153
+ return {
154
+ agentName: meta.name,
155
+ results: [],
156
+ durationMs: Date.now() - start,
157
+ error: error instanceof Error ? error.message : String(error),
158
+ };
159
+ }
160
+ }
161
+ function deduplicateResults(results) {
162
+ const seen = new Map();
163
+ const deduped = [];
164
+ for (const result of results) {
165
+ const key = `${result.title}:${result.file}`;
166
+ const seenLines = seen.get(key);
167
+ if (seenLines) {
168
+ if (seenLines.some((l) => Math.abs(l - result.line) <= 2))
169
+ continue;
170
+ seenLines.push(result.line);
171
+ }
172
+ else {
173
+ seen.set(key, [result.line]);
174
+ }
175
+ deduped.push(result);
176
+ }
177
+ return deduped;
178
+ }
179
+ function calculateScore(results) {
180
+ let score = 100;
181
+ for (const result of results) {
182
+ score -= SEVERITY_PENALTY[result.severity] ?? 0;
183
+ }
184
+ return Math.max(0, score);
185
+ }
186
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/scanning/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Technology } from "./types.js";
2
+ export interface TechDetectionResult {
3
+ technologies: Technology[];
4
+ /** Raw details: which rule matched and how. */
5
+ details: Map<Technology, string>;
6
+ }
7
+ /**
8
+ * Detect technologies used in a repository by analyzing file names and content.
9
+ * Works with the existing Map<string, string> file representation.
10
+ */
11
+ export declare function detectTechnologies(files: Map<string, string>): TechDetectionResult;
12
+ //# sourceMappingURL=tech-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tech-detector.d.ts","sourceRoot":"","sources":["../../src/scanning/tech-detector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAuM7C,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,+CAA+C;IAC/C,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,mBAAmB,CAoDlF"}
@@ -0,0 +1,252 @@
1
+ // Automatic technology detection from repository files.
2
+ // Analyzes package manifests, config files, and imports to determine
3
+ // which technologies a project uses. This drives which ScanAgents run.
4
+ const DETECTION_RULES = [
5
+ // --- JavaScript / TypeScript ecosystem ---
6
+ {
7
+ tech: "nodejs",
8
+ files: [/^package\.json$/],
9
+ },
10
+ {
11
+ tech: "nextjs",
12
+ npmDeps: ["next"],
13
+ files: [/^next\.config\.[tjm]s$/],
14
+ },
15
+ {
16
+ tech: "react",
17
+ npmDeps: ["react", "react-dom"],
18
+ },
19
+ {
20
+ tech: "express",
21
+ npmDeps: ["express"],
22
+ },
23
+ {
24
+ tech: "fastify",
25
+ npmDeps: ["fastify"],
26
+ },
27
+ {
28
+ tech: "hono",
29
+ npmDeps: ["hono"],
30
+ },
31
+ {
32
+ tech: "koa",
33
+ npmDeps: ["koa"],
34
+ },
35
+ {
36
+ tech: "nestjs",
37
+ npmDeps: ["@nestjs/core"],
38
+ },
39
+ {
40
+ tech: "react-native",
41
+ npmDeps: ["react-native"],
42
+ files: [/^app\.json$/],
43
+ },
44
+ {
45
+ tech: "expo",
46
+ npmDeps: ["expo"],
47
+ files: [/^app\.json$/, /^app\.config\.[tj]s$/],
48
+ },
49
+ {
50
+ tech: "prisma",
51
+ npmDeps: ["prisma", "@prisma/client"],
52
+ files: [/prisma\/schema\.prisma$/],
53
+ },
54
+ {
55
+ tech: "graphql",
56
+ npmDeps: ["graphql", "apollo-server", "@apollo/server", "type-graphql"],
57
+ },
58
+ {
59
+ tech: "stripe",
60
+ npmDeps: ["stripe"],
61
+ },
62
+ {
63
+ tech: "mongodb",
64
+ npmDeps: ["mongodb", "mongoose"],
65
+ },
66
+ {
67
+ tech: "redis",
68
+ npmDeps: ["redis", "ioredis"],
69
+ },
70
+ {
71
+ tech: "vue",
72
+ npmDeps: ["vue"],
73
+ },
74
+ {
75
+ tech: "angular",
76
+ npmDeps: ["@angular/core"],
77
+ },
78
+ {
79
+ tech: "svelte",
80
+ npmDeps: ["svelte"],
81
+ },
82
+ // --- Python ecosystem ---
83
+ {
84
+ tech: "python",
85
+ files: [/^requirements\.txt$/, /^pyproject\.toml$/, /^setup\.py$/, /^Pipfile$/],
86
+ },
87
+ {
88
+ tech: "django",
89
+ files: [/^requirements\.txt$/, /^pyproject\.toml$/],
90
+ contentPatterns: [/django/i],
91
+ },
92
+ {
93
+ tech: "flask",
94
+ files: [/^requirements\.txt$/, /^pyproject\.toml$/],
95
+ contentPatterns: [/flask/i],
96
+ },
97
+ {
98
+ tech: "fastapi",
99
+ files: [/^requirements\.txt$/, /^pyproject\.toml$/],
100
+ contentPatterns: [/fastapi/i],
101
+ },
102
+ // --- Go ---
103
+ {
104
+ tech: "go",
105
+ files: [/^go\.mod$/],
106
+ },
107
+ // --- Java / Kotlin ---
108
+ {
109
+ tech: "java",
110
+ files: [/^pom\.xml$/, /^build\.gradle(?:\.kts)?$/],
111
+ },
112
+ {
113
+ tech: "spring",
114
+ files: [/^pom\.xml$/, /^build\.gradle(?:\.kts)?$/],
115
+ contentPatterns: [/spring-boot|springframework/i],
116
+ },
117
+ {
118
+ tech: "kotlin",
119
+ files: [/^build\.gradle\.kts$/],
120
+ contentPatterns: [/kotlin/i],
121
+ },
122
+ // --- PHP ---
123
+ {
124
+ tech: "php",
125
+ files: [/^composer\.json$/],
126
+ },
127
+ {
128
+ tech: "laravel",
129
+ files: [/^composer\.json$/],
130
+ contentPatterns: [/laravel/i],
131
+ },
132
+ // --- Ruby ---
133
+ {
134
+ tech: "ruby",
135
+ files: [/^Gemfile$/],
136
+ },
137
+ {
138
+ tech: "rails",
139
+ files: [/^Gemfile$/],
140
+ contentPatterns: [/rails/i],
141
+ },
142
+ // --- Dart / Flutter ---
143
+ {
144
+ tech: "dart",
145
+ files: [/^pubspec\.yaml$/],
146
+ },
147
+ {
148
+ tech: "flutter",
149
+ files: [/^pubspec\.yaml$/],
150
+ contentPatterns: [/flutter/i],
151
+ },
152
+ // --- .NET ---
153
+ {
154
+ tech: "dotnet",
155
+ files: [/\.csproj$/, /\.fsproj$/, /\.sln$/],
156
+ },
157
+ // --- Rust ---
158
+ {
159
+ tech: "rust",
160
+ files: [/^Cargo\.toml$/],
161
+ },
162
+ // --- Infrastructure ---
163
+ {
164
+ tech: "docker",
165
+ files: [/^Dockerfile$/, /^docker-compose\.ya?ml$/],
166
+ },
167
+ // --- BaaS ---
168
+ {
169
+ tech: "firebase",
170
+ files: [/^firebase\.json$/, /^\.firebaserc$/, /^firestore\.rules$/],
171
+ npmDeps: ["firebase", "firebase-admin"],
172
+ },
173
+ {
174
+ tech: "supabase",
175
+ files: [/^supabase\/config\.toml$/],
176
+ npmDeps: ["@supabase/supabase-js"],
177
+ },
178
+ ];
179
+ /**
180
+ * Detect technologies used in a repository by analyzing file names and content.
181
+ * Works with the existing Map<string, string> file representation.
182
+ */
183
+ export function detectTechnologies(files) {
184
+ const detected = new Set();
185
+ const details = new Map();
186
+ const filePaths = [...files.keys()];
187
+ // Parse package.json deps once (used by many rules)
188
+ const allNpmDeps = extractNpmDeps(files);
189
+ for (const rule of DETECTION_RULES) {
190
+ if (detected.has(rule.tech))
191
+ continue;
192
+ // Check npm dependencies
193
+ if (rule.npmDeps) {
194
+ const matchedDep = rule.npmDeps.find((dep) => allNpmDeps.has(dep));
195
+ if (matchedDep) {
196
+ detected.add(rule.tech);
197
+ details.set(rule.tech, `npm dependency: ${matchedDep}`);
198
+ continue;
199
+ }
200
+ }
201
+ // Check file existence + optional content patterns
202
+ if (rule.files) {
203
+ for (const filePattern of rule.files) {
204
+ const matchingFile = filePaths.find((fp) => filePattern.test(fp));
205
+ if (!matchingFile)
206
+ continue;
207
+ if (!rule.contentPatterns) {
208
+ // File existence alone is enough
209
+ detected.add(rule.tech);
210
+ details.set(rule.tech, `file: ${matchingFile}`);
211
+ break;
212
+ }
213
+ // Check file content
214
+ const content = files.get(matchingFile);
215
+ if (!content)
216
+ continue;
217
+ const matchedPattern = rule.contentPatterns.find((p) => p.test(content));
218
+ if (matchedPattern) {
219
+ detected.add(rule.tech);
220
+ details.set(rule.tech, `file: ${matchingFile} (content match)`);
221
+ break;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ return {
227
+ technologies: [...detected].sort(),
228
+ details,
229
+ };
230
+ }
231
+ /** Extract all dependency names from package.json (deps + devDeps). */
232
+ function extractNpmDeps(files) {
233
+ const deps = new Set();
234
+ const packageJson = files.get("package.json");
235
+ if (!packageJson)
236
+ return deps;
237
+ try {
238
+ const pkg = JSON.parse(packageJson);
239
+ for (const key of ["dependencies", "devDependencies", "peerDependencies"]) {
240
+ if (pkg[key] && typeof pkg[key] === "object") {
241
+ for (const name of Object.keys(pkg[key])) {
242
+ deps.add(name);
243
+ }
244
+ }
245
+ }
246
+ }
247
+ catch {
248
+ // Malformed package.json — skip
249
+ }
250
+ return deps;
251
+ }
252
+ //# sourceMappingURL=tech-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tech-detector.js","sourceRoot":"","sources":["../../src/scanning/tech-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ export type Severity = "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFO";
2
+ export interface ScanResult {
3
+ title: string;
4
+ severity: Severity;
5
+ file: string;
6
+ line: number;
7
+ description: string;
8
+ fix: string;
9
+ cwe?: string;
10
+ /** Links this finding back to a CheckDefinition.id for scan log tracking. */
11
+ checkId?: string;
12
+ /**
13
+ * Confidence level for this finding.
14
+ * high — direct pattern match, no ambiguity (DEBUG=True, pickle.loads with user input)
15
+ * medium — good signal but context-dependent (SQL f-string that might be parameterized)
16
+ * low — broad match or absence-based (missing auth decorator, Flask CORS default)
17
+ */
18
+ confidence?: "high" | "medium" | "low";
19
+ }
20
+ export interface AgentMetadata {
21
+ name: string;
22
+ version: string;
23
+ technologies: string[];
24
+ }
25
+ export interface ScanReport {
26
+ score: number;
27
+ results: ScanResult[];
28
+ techsDetected: string[];
29
+ timestamp: string;
30
+ }
31
+ /**
32
+ * ScanAgent interface — every technology-specific scanner implements this.
33
+ * Agents are self-contained: they know how to detect their technology
34
+ * and how to scan for vulnerabilities within it.
35
+ */
36
+ export interface ScanAgent {
37
+ /** Check if this agent's technology exists in the repo. */
38
+ detect(files: Map<string, string>): Promise<boolean>;
39
+ /** Run the security scan. Only called if detect() returned true. */
40
+ scan(files: Map<string, string>): Promise<ScanResult[]>;
41
+ /** Return metadata about this agent (name, version, supported techs). */
42
+ getMetadata(): AgentMetadata;
43
+ /** Return the list of checks this agent can perform (for scan log). */
44
+ getChecks?(): CheckDefinition[];
45
+ }
46
+ /** Technology identifiers returned by TechDetector. */
47
+ export type Technology = "nodejs" | "nextjs" | "react" | "express" | "fastify" | "hono" | "koa" | "nestjs" | "python" | "django" | "flask" | "fastapi" | "go" | "java" | "spring" | "kotlin" | "php" | "laravel" | "ruby" | "rails" | "dart" | "flutter" | "dotnet" | "rust" | "docker" | "firebase" | "supabase" | "react-native" | "expo" | "prisma" | "mongodb" | "redis" | "graphql" | "stripe" | "vue" | "angular" | "svelte";
48
+ /** A check that an agent can perform. */
49
+ export interface CheckDefinition {
50
+ id: string;
51
+ name: string;
52
+ severity: Severity;
53
+ }
54
+ /** Result of a single check after a scan. */
55
+ export interface CheckResult {
56
+ checkId: string;
57
+ status: "pass" | "fail";
58
+ findingCount: number;
59
+ }
60
+ /** Log entry for one agent's execution. */
61
+ export interface AgentLogEntry {
62
+ agentName: string;
63
+ agentVersion: string;
64
+ technologies: string[];
65
+ status: "completed" | "error" | "timeout" | "skipped";
66
+ durationMs: number;
67
+ checkResults: CheckResult[];
68
+ totalChecks: number;
69
+ passed: number;
70
+ failed: number;
71
+ error?: string;
72
+ }
73
+ /** Complete scan execution log. */
74
+ export interface ScanLog {
75
+ technologiesDetected: string[];
76
+ technologyDetails: Record<string, string>;
77
+ agentsMatched: string[];
78
+ agentsConfirmed: string[];
79
+ agentLogs: AgentLogEntry[];
80
+ totalDurationMs: number;
81
+ summary: {
82
+ totalChecks: number;
83
+ passed: number;
84
+ failed: number;
85
+ };
86
+ }
87
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scanning/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ // Multi-technology scanning architecture — shared types.
2
+ // This is the new agent-based system. The existing engines/ directory
3
+ // handles the current Next.js-focused scanner and remains untouched.
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scanning/types.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,sEAAsE;AACtE,qEAAqE"}
@@ -0,0 +1,2 @@
1
+ export { execFile } from "node:child_process";
2
+ //# sourceMappingURL=child-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process.d.ts","sourceRoot":"","sources":["../../src/utils/child-process.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Re-export child_process functions for testability.
2
+ // Vitest cannot reliably mock node:child_process builtins.
3
+ export { execFile } from "node:child_process";
4
+ //# sourceMappingURL=child-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process.js","sourceRoot":"","sources":["../../src/utils/child-process.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,2DAA2D;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FindingContext } from "../engines/types.js";
2
+ interface ClassifyInput {
3
+ file_path?: string;
4
+ code_snippet?: string;
5
+ }
6
+ export declare function classifyContext(input: ClassifyInput): FindingContext;
7
+ export declare function classifyFindings<T extends ClassifyInput & {
8
+ context?: FindingContext;
9
+ }>(findings: T[]): T[];
10
+ export {};
11
+ //# sourceMappingURL=context-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-classifier.d.ts","sourceRoot":"","sources":["../../src/utils/context-classifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,UAAU,aAAa;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAapE;AAED,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG;IAAE,OAAO,CAAC,EAAE,cAAc,CAAA;CAAE,EACrF,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE,CAKL"}