@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,237 @@
1
+ // Scan orchestrator - runs all engines in parallel and aggregates results
2
+ import { runSecretsEngine } from "./engines/secrets.js";
3
+ import { analyzePatterns } from "./engines/patterns.js";
4
+ import { analyzeDependencies } from "./engines/dependencies.js";
5
+ import { analyzeConfig } from "./engines/config.js";
6
+ import { scanUrl } from "./engines/url-scanner.js";
7
+ import { analyzeDbRules } from "./engines/db-rules.js";
8
+ import { runGitleaks } from "./engines/gitleaks.js";
9
+ import { runSemgrep } from "./engines/semgrep.js";
10
+ import { runNpmAudit } from "./engines/npm-audit.js";
11
+ import { runDast } from "./engines/dast.js";
12
+ import { analyzeGitHubActions } from "./engines/github-actions.js";
13
+ import { runMultiTechScan } from "./scanning/orchestrator.js";
14
+ import { classifyFindings } from "./utils/context-classifier.js";
15
+ import { postProcessFindings } from "./utils/post-processor.js";
16
+ import { detectTechnologies } from "./scanning/tech-detector.js";
17
+ export async function runScan(params) {
18
+ const startTime = Date.now();
19
+ const engineResults = [];
20
+ let scanLog;
21
+ // Run code analysis engines in parallel
22
+ const codeEnginePromises = [
23
+ // Regex-based engines (always run, work on Map<string, string>)
24
+ runEngine("secrets", () => runSecretsEngine(params.files)),
25
+ runEngine("patterns", () => analyzePatterns(params.files)),
26
+ runEngine("dependencies", () => analyzeDependencies(params.files)),
27
+ runEngine("config", () => analyzeConfig(params.files)),
28
+ runEngine("github-actions", () => analyzeGitHubActions(params.files)),
29
+ // Multi-tech agents (Python, Go, Java, PHP, C#, Mobile, Supabase).
30
+ // The javascript-agent is excluded: it is an adapter around the legacy
31
+ // engines above and would duplicate every JS finding.
32
+ runEngine("multi-tech-agents", async () => {
33
+ const report = await runMultiTechScan(params.files, { exclude: ["javascript-agent"] });
34
+ scanLog = report.scanLog;
35
+ return report.results.map(agentResultToFinding);
36
+ }, 120_000),
37
+ // External tool engines (only when filesystem is available)
38
+ ...(params.repoDir ? [
39
+ runEngine("gitleaks", () => runGitleaks(params.repoDir)),
40
+ runEngine("semgrep", () => runSemgrep(params.repoDir)),
41
+ runEngine("npm-audit", () => runNpmAudit(params.repoDir, params.files)),
42
+ ] : []),
43
+ ];
44
+ // Conditionally run URL scanner + DAST
45
+ if (params.appUrl) {
46
+ codeEnginePromises.push(runEngine("url-scanner", () => scanUrl(params.appUrl)), runEngine("dast", () => runDast(params.appUrl), 180_000) // DAST needs more time
47
+ );
48
+ }
49
+ // Conditionally run DB rules parser
50
+ if (params.dbRulesInput) {
51
+ codeEnginePromises.push(runEngine("db-rules", () => analyzeDbRules(params.dbRulesInput, "auto")));
52
+ }
53
+ const results = await Promise.allSettled(codeEnginePromises);
54
+ for (const result of results) {
55
+ if (result.status === "fulfilled") {
56
+ engineResults.push(result.value);
57
+ }
58
+ }
59
+ // Aggregate findings
60
+ const allFindings = [];
61
+ const failedEngines = [];
62
+ for (const engineResult of engineResults) {
63
+ if (engineResult.error) {
64
+ failedEngines.push(engineResult.engine);
65
+ }
66
+ allFindings.push(...engineResult.findings);
67
+ }
68
+ // Deduplicate findings by vulnerability_id + file_path + line_number
69
+ const deduplicated = deduplicateFindings(allFindings);
70
+ // Classify findings by context (production, test, example, etc.)
71
+ const classified = classifyFindings(deduplicated);
72
+ // Post-process: framework suppressions, cross-engine dedup, contextual notes,
73
+ // and actionable/informational classification.
74
+ const technologies = detectTechnologies(params.files).technologies;
75
+ const postProcessed = postProcessFindings(classified, technologies);
76
+ // Calculate score (only production findings penalize; framework requirements skipped)
77
+ const score = calculateScore(postProcessed);
78
+ // Build summary with context breakdown
79
+ const summary = buildSummary(postProcessed);
80
+ return {
81
+ findings: postProcessed,
82
+ engineResults,
83
+ score,
84
+ summary,
85
+ failedEngines,
86
+ durationMs: Date.now() - startTime,
87
+ scanLog,
88
+ };
89
+ }
90
+ // Agent findings carry their own title/description/fix inline, so they don't
91
+ // map to the numeric vulnerability catalog. We derive a stable synthetic id
92
+ // (>= 100000, outside the catalog range) from the checkId so deduplication
93
+ // by vulnerability_id + file + line keeps working.
94
+ function syntheticVulnId(key) {
95
+ let hash = 0;
96
+ for (let i = 0; i < key.length; i++) {
97
+ hash = (hash * 31 + key.charCodeAt(i)) | 0;
98
+ }
99
+ return 100000 + (Math.abs(hash) % 100000);
100
+ }
101
+ function agentResultToFinding(result) {
102
+ const category = result.checkId?.split(":")[0] ?? "multi-tech";
103
+ return {
104
+ vulnerability_id: syntheticVulnId(result.checkId ?? result.title),
105
+ severity: result.severity.toLowerCase(),
106
+ category,
107
+ title: result.title,
108
+ description_simple: result.description,
109
+ file_path: result.file,
110
+ line_number: result.line,
111
+ fix_description: result.fix,
112
+ owasp_ref: result.cwe,
113
+ status: "open",
114
+ confidence: result.confidence,
115
+ };
116
+ }
117
+ const ENGINE_TIMEOUT_MS = 90_000; // 90s default per-engine safety timeout
118
+ async function runEngine(name, fn, timeoutMs = ENGINE_TIMEOUT_MS) {
119
+ const startTime = Date.now();
120
+ try {
121
+ const findings = await Promise.race([
122
+ fn(),
123
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Engine ${name} timed out after ${timeoutMs}ms`)), timeoutMs)),
124
+ ]);
125
+ return {
126
+ engine: name,
127
+ findings,
128
+ durationMs: Date.now() - startTime,
129
+ };
130
+ }
131
+ catch (error) {
132
+ return {
133
+ engine: name,
134
+ findings: [],
135
+ error: error instanceof Error ? error.message : "Unknown error",
136
+ durationMs: Date.now() - startTime,
137
+ };
138
+ }
139
+ }
140
+ function deduplicateFindings(findings) {
141
+ // Fuzzy dedup: same vulnerability_id + file_path within ±2 lines = duplicate.
142
+ // This handles Semgrep (AST node start) vs regex (first match line) differences.
143
+ const result = [];
144
+ const seen = new Map(); // baseKey → array of seen line numbers
145
+ for (const finding of findings) {
146
+ const baseKey = `${finding.vulnerability_id}:${finding.file_path ?? ""}`;
147
+ const lineNum = finding.line_number ?? 0;
148
+ const seenLines = seen.get(baseKey);
149
+ if (seenLines) {
150
+ const isDuplicate = seenLines.some((l) => Math.abs(l - lineNum) <= 2);
151
+ if (isDuplicate)
152
+ continue;
153
+ seenLines.push(lineNum);
154
+ }
155
+ else {
156
+ seen.set(baseKey, [lineNum]);
157
+ }
158
+ result.push(finding);
159
+ }
160
+ return result;
161
+ }
162
+ const CONTEXT_PENALTY = {
163
+ production: 1.0,
164
+ config: 0, // Config/scripts/migrations are infrastructure, not production code
165
+ test: 0,
166
+ example: 0,
167
+ rule: 0,
168
+ vendored: 0,
169
+ };
170
+ const CONFIDENCE_MULTIPLIER = {
171
+ high: 1.0, // Semgrep AST-based, high confidence
172
+ medium: 0.7, // Regex pattern with good specificity
173
+ low: 0.3, // Absence checks, broad regex matches
174
+ };
175
+ function calculateScore(findings) {
176
+ const penalties = {
177
+ critical: 15,
178
+ high: 10,
179
+ medium: 5,
180
+ low: 2,
181
+ info: 0,
182
+ };
183
+ let score = 100;
184
+ for (const finding of findings) {
185
+ if (finding.status === "open") {
186
+ // Framework requirements are expected behaviour — do not penalize the score.
187
+ if (finding.is_framework_requirement)
188
+ continue;
189
+ const ctx = finding.context ?? "production";
190
+ const contextMul = CONTEXT_PENALTY[ctx] ?? 1;
191
+ const confidenceMul = CONFIDENCE_MULTIPLIER[finding.confidence ?? "medium"];
192
+ score -= (penalties[finding.severity] ?? 0) * contextMul * confidenceMul;
193
+ }
194
+ }
195
+ return Math.max(0, Math.round(score));
196
+ }
197
+ function buildSummary(findings) {
198
+ const summary = {
199
+ total: 0, critical: 0, high: 0, medium: 0, low: 0, info: 0,
200
+ allFindings: 0,
201
+ production: 0, nonProduction: 0,
202
+ byContext: {},
203
+ actionable: 0,
204
+ informational: 0,
205
+ };
206
+ for (const finding of findings) {
207
+ summary.allFindings++;
208
+ const ctx = finding.context ?? "production";
209
+ if (ctx === "production") {
210
+ summary.production++;
211
+ if (finding.classification === "informational") {
212
+ summary.informational++;
213
+ }
214
+ else {
215
+ // Only actionable findings count toward headline totals and severity breakdown
216
+ summary.actionable++;
217
+ summary.total++;
218
+ if (finding.severity === "critical")
219
+ summary.critical++;
220
+ else if (finding.severity === "high")
221
+ summary.high++;
222
+ else if (finding.severity === "medium")
223
+ summary.medium++;
224
+ else if (finding.severity === "low")
225
+ summary.low++;
226
+ else if (finding.severity === "info")
227
+ summary.info++;
228
+ }
229
+ }
230
+ else {
231
+ summary.nonProduction++;
232
+ }
233
+ summary.byContext[ctx] = (summary.byContext[ctx] ?? 0) + 1;
234
+ }
235
+ return summary;
236
+ }
237
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAmCjE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,MAAkB;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAmB,EAAE,CAAC;IACzC,IAAI,OAA4B,CAAC;IAEjC,wCAAwC;IACxC,MAAM,kBAAkB,GAAG;QACzB,gEAAgE;QAChE,SAAS,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1D,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1D,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClE,SAAS,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,SAAS,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrE,mEAAmE;QACnE,uEAAuE;QACvE,sDAAsD;QACtD,SAAS,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACvF,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;YACzB,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClD,CAAC,EAAE,OAAO,CAAC;QACX,4DAA4D;QAC5D,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YACnB,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;YACzD,SAAS,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;YACvD,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,OAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;SACzE,CAAC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,uCAAuC;IACvC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,kBAAkB,CAAC,IAAI,CACrB,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAO,CAAC,CAAC,EACvD,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAO,CAAC,EAAE,OAAO,CAAC,CAAC,uBAAuB;SAClF,CAAC;IACJ,CAAC;IAED,oCAAoC;IACpC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,kBAAkB,CAAC,IAAI,CACrB,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,CACzB,cAAc,CAAC,MAAM,CAAC,YAAa,EAAE,MAAM,CAAC,CAC7C,CACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAE7D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,WAAW,GAAkB,EAAE,CAAC;IACtC,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YACvB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,qEAAqE;IACrE,MAAM,YAAY,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAEtD,iEAAiE;IACjE,MAAM,UAAU,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAElD,8EAA8E;IAC9E,+CAA+C;IAC/C,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;IACnE,MAAM,aAAa,GAAG,mBAAmB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAEpE,sFAAsF;IACtF,MAAM,KAAK,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAE5C,uCAAuC;IACvC,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;IAE5C,OAAO;QACL,QAAQ,EAAE,aAAa;QACvB,aAAa;QACb,KAAK;QACL,OAAO;QACP,aAAa;QACb,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QAClC,OAAO;KACR,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,4EAA4E;AAC5E,2EAA2E;AAC3E,mDAAmD;AACnD,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAuB;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;IAC/D,OAAO;QACL,gBAAgB,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC;QACjE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAc;QACnD,QAAQ;QACR,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,kBAAkB,EAAE,MAAM,CAAC,WAAW;QACtC,SAAS,EAAE,MAAM,CAAC,IAAI;QACtB,WAAW,EAAE,MAAM,CAAC,IAAI;QACxB,eAAe,EAAE,MAAM,CAAC,GAAG;QAC3B,SAAS,EAAE,MAAM,CAAC,GAAG;QACrB,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,CAAC,wCAAwC;AAE1E,KAAK,UAAU,SAAS,CACtB,IAAY,EACZ,EAAgD,EAChD,YAAoB,iBAAiB;IAErC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAClC,EAAE,EAAE;YACJ,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CACR,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,oBAAoB,SAAS,IAAI,CAAC,CAAC,EACxE,SAAS,CACV,CACF;SACF,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACnC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;YAC/D,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACnC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAuB;IAClD,8EAA8E;IAC9E,iFAAiF;IACjF,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC,CAAC,uCAAuC;IAEjF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QACzE,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACtE,IAAI,WAAW;gBAAE,SAAS;YAC1B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,eAAe,GAAmC;IACtD,UAAU,EAAE,GAAG;IACf,MAAM,EAAE,CAAC,EAAK,oEAAoE;IAClF,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,qBAAqB,GAAsC;IAC/D,IAAI,EAAE,GAAG,EAAK,qCAAqC;IACnD,MAAM,EAAE,GAAG,EAAG,sCAAsC;IACpD,GAAG,EAAE,GAAG,EAAM,sCAAsC;CACrD,CAAC;AAEF,SAAS,cAAc,CAAC,QAAuB;IAC7C,MAAM,SAAS,GAA2B;QACxC,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;KACR,CAAC;IAEF,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9B,6EAA6E;YAC7E,IAAI,OAAO,CAAC,wBAAwB;gBAAE,SAAS;YAE/C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,CAAC;YAC5C,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC;YAC5E,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,GAAG,aAAa,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,YAAY,CAAC,QAAuB;IAC3C,MAAM,OAAO,GAA0B;QACrC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;QAC1D,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC;QAC/B,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,CAAC;QACb,aAAa,EAAE,CAAC;KACjB,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,WAAW,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,CAAC;QAE5C,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,OAAO,CAAC,UAAU,EAAE,CAAC;YAErB,IAAI,OAAO,CAAC,cAAc,KAAK,eAAe,EAAE,CAAC;gBAC/C,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,+EAA+E;gBAC/E,OAAO,CAAC,UAAU,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,IAAI,OAAO,CAAC,QAAQ,KAAK,UAAU;oBAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;qBACnD,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;oBAAE,OAAO,CAAC,IAAI,EAAE,CAAC;qBAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;oBAAE,OAAO,CAAC,MAAM,EAAE,CAAC;qBACpD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK;oBAAE,OAAO,CAAC,GAAG,EAAE,CAAC;qBAC9C,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;oBAAE,OAAO,CAAC,IAAI,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
File without changes
@@ -0,0 +1,199 @@
1
+ rules:
2
+ # =============================================
3
+ # AI / LLM Security (IDs 200-208)
4
+ # =============================================
5
+
6
+ - id: datahogo-ai-prompt-injection
7
+ patterns:
8
+ - pattern-either:
9
+ - pattern: |
10
+ $MESSAGES = `...${$USER_INPUT}...`
11
+ - pattern: |
12
+ $MESSAGES.push({..., content: `...${$INPUT}...`})
13
+ - pattern: |
14
+ $CLIENT.messages.create({..., messages: [{..., content: `...${$INPUT}...`}]})
15
+ message: >
16
+ User input is interpolated directly into an LLM prompt. This enables prompt injection attacks
17
+ where an attacker can manipulate the AI's behavior. Sanitize or use structured prompts with
18
+ system/user role separation.
19
+ severity: WARNING
20
+ languages: [typescript, javascript]
21
+ metadata:
22
+ datahogo_id: 200
23
+ owasp: "A03:2021"
24
+ category: ai-llm
25
+
26
+ - id: datahogo-ai-api-key-frontend
27
+ patterns:
28
+ - pattern-either:
29
+ - pattern: process.env.NEXT_PUBLIC_ANTHROPIC_API_KEY
30
+ - pattern: process.env.NEXT_PUBLIC_OPENAI_API_KEY
31
+ - pattern: process.env.NEXT_PUBLIC_AI_API_KEY
32
+ - pattern: process.env.NEXT_PUBLIC_CLAUDE_API_KEY
33
+ message: >
34
+ AI API key is exposed via NEXT_PUBLIC_ environment variable, making it accessible in the browser.
35
+ AI API keys must only be used server-side.
36
+ severity: ERROR
37
+ languages: [typescript, javascript]
38
+ metadata:
39
+ datahogo_id: 203
40
+ owasp: "A07:2021"
41
+ category: ai-llm
42
+
43
+ - id: datahogo-ai-output-eval
44
+ patterns:
45
+ - pattern-either:
46
+ - pattern: eval($AI_RESPONSE)
47
+ - pattern: new Function($AI_RESPONSE)
48
+ - pattern: eval($COMPLETION.content)
49
+ - pattern: eval($RESPONSE.choices[0].message.content)
50
+ message: >
51
+ AI-generated output is passed to eval() or Function constructor. Never execute AI output as code —
52
+ it can be manipulated via prompt injection to run arbitrary code.
53
+ severity: ERROR
54
+ languages: [typescript, javascript]
55
+ metadata:
56
+ datahogo_id: 208
57
+ owasp: "A03:2021"
58
+ category: ai-llm
59
+
60
+ - id: datahogo-ai-no-output-sanitization
61
+ patterns:
62
+ - pattern: |
63
+ dangerouslySetInnerHTML={{__html: $AI_OUTPUT}}
64
+ - metavariable-regex:
65
+ metavariable: $AI_OUTPUT
66
+ regex: ".*(completion|response|aiOutput|generated|llm|chat|gpt|claude).*"
67
+ message: >
68
+ AI-generated content is rendered as HTML without sanitization. AI outputs can contain XSS payloads
69
+ via prompt injection. Always sanitize with DOMPurify before rendering.
70
+ severity: WARNING
71
+ languages: [typescript, javascript]
72
+ metadata:
73
+ datahogo_id: 204
74
+ category: ai-llm
75
+
76
+ # =============================================
77
+ # Database Connection Security (IDs 209-220)
78
+ # =============================================
79
+
80
+ - id: datahogo-db-connection-no-ssl
81
+ patterns:
82
+ - pattern-either:
83
+ - pattern: |
84
+ new Pool({..., ssl: false})
85
+ - pattern: |
86
+ new Client({..., ssl: false})
87
+ - pattern: |
88
+ createConnection({..., ssl: false})
89
+ message: >
90
+ Database connection has SSL explicitly disabled. Always use SSL/TLS for database connections
91
+ to prevent credential and data interception.
92
+ severity: WARNING
93
+ languages: [typescript, javascript]
94
+ metadata:
95
+ datahogo_id: 209
96
+ category: database-connection
97
+
98
+ - id: datahogo-db-ssl-reject-unauthorized-false
99
+ pattern: |
100
+ ssl: { rejectUnauthorized: false }
101
+ message: >
102
+ Database SSL certificate validation is disabled. This makes the connection vulnerable to
103
+ man-in-the-middle attacks. Use a proper CA certificate instead.
104
+ severity: WARNING
105
+ languages: [typescript, javascript]
106
+ metadata:
107
+ datahogo_id: 219
108
+ category: database-connection
109
+
110
+ - id: datahogo-db-default-credentials
111
+ patterns:
112
+ - pattern-regex: "(?:postgres|mysql|mongodb)://(?:postgres|root|admin):(?:postgres|root|admin|password|secret|test)@"
113
+ message: >
114
+ Database connection string uses default credentials. Use strong, unique passwords
115
+ managed via environment variables or a secrets manager.
116
+ severity: ERROR
117
+ languages: [typescript, javascript]
118
+ metadata:
119
+ datahogo_id: 211
120
+ category: database-connection
121
+
122
+ - id: datahogo-db-connection-string-logged
123
+ patterns:
124
+ - pattern-either:
125
+ - pattern: console.log(process.env.DATABASE_URL)
126
+ - pattern: console.log($X.connectionString)
127
+ - pattern: console.log(..., process.env.DATABASE_URL, ...)
128
+ - pattern: console.error(process.env.DATABASE_URL)
129
+ message: >
130
+ Database connection string (which may contain credentials) is logged. Remove logging of
131
+ connection strings to prevent credential exposure.
132
+ severity: WARNING
133
+ languages: [typescript, javascript]
134
+ metadata:
135
+ datahogo_id: 218
136
+ category: database-connection
137
+
138
+ - id: datahogo-db-hardcoded-host
139
+ patterns:
140
+ - pattern-regex: "host:\\s*['\"]\\w+\\.(?:rds\\.amazonaws\\.com|database\\.azure\\.com|cloudsql\\.google\\.com)['\"]"
141
+ message: >
142
+ Database host is hardcoded to a cloud provider endpoint. Use environment variables
143
+ to allow different configurations per environment.
144
+ severity: INFO
145
+ languages: [typescript, javascript]
146
+ metadata:
147
+ datahogo_id: 220
148
+ category: database-connection
149
+
150
+ # =============================================
151
+ # Cloud Provider Security (IDs 221-232)
152
+ # =============================================
153
+
154
+ - id: datahogo-cloud-metadata-ssrf
155
+ patterns:
156
+ - pattern-either:
157
+ - pattern: fetch("http://169.254.169.254/...")
158
+ - pattern: fetch(`http://169.254.169.254/...`)
159
+ - pattern: axios.get("http://169.254.169.254/...")
160
+ message: >
161
+ Request to cloud metadata endpoint detected. If user input can influence this URL,
162
+ it enables SSRF attacks to steal cloud credentials. Block metadata IPs in your HTTP client.
163
+ severity: ERROR
164
+ languages: [typescript, javascript]
165
+ metadata:
166
+ datahogo_id: 222
167
+ owasp: "A10:2021"
168
+ category: cloud
169
+
170
+ - id: datahogo-cloud-iam-star-star
171
+ patterns:
172
+ - pattern-regex: '"Action"\\s*:\\s*"\\*"[\\s\\S]{0,100}"Resource"\\s*:\\s*"\\*"'
173
+ message: >
174
+ IAM policy grants full access (Action: *, Resource: *). Follow least-privilege principle —
175
+ specify only the actions and resources needed.
176
+ severity: WARNING
177
+ languages: [json]
178
+ metadata:
179
+ datahogo_id: 224
180
+ category: cloud
181
+
182
+ - id: datahogo-cloud-s3-public
183
+ patterns:
184
+ - pattern-either:
185
+ - pattern: |
186
+ new s3.Bucket({..., publicReadAccess: true})
187
+ - pattern: |
188
+ ACL: "public-read"
189
+ - pattern: |
190
+ ACL: "public-read-write"
191
+ message: >
192
+ S3 bucket configured with public access. Unless intentionally serving public static assets,
193
+ buckets should be private with CloudFront or presigned URLs for access.
194
+ severity: ERROR
195
+ languages: [typescript, javascript]
196
+ metadata:
197
+ datahogo_id: 221
198
+ owasp: "A05:2021"
199
+ category: cloud