@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.
- package/LICENSE +661 -0
- package/README.md +17 -0
- package/dist/engines/config.d.ts +3 -0
- package/dist/engines/config.d.ts.map +1 -0
- package/dist/engines/config.js +433 -0
- package/dist/engines/config.js.map +1 -0
- package/dist/engines/dast.d.ts +3 -0
- package/dist/engines/dast.d.ts.map +1 -0
- package/dist/engines/dast.js +167 -0
- package/dist/engines/dast.js.map +1 -0
- package/dist/engines/db-rules.d.ts +3 -0
- package/dist/engines/db-rules.d.ts.map +1 -0
- package/dist/engines/db-rules.js +166 -0
- package/dist/engines/db-rules.js.map +1 -0
- package/dist/engines/dependencies.d.ts +3 -0
- package/dist/engines/dependencies.d.ts.map +1 -0
- package/dist/engines/dependencies.js +167 -0
- package/dist/engines/dependencies.js.map +1 -0
- package/dist/engines/github-actions.d.ts +3 -0
- package/dist/engines/github-actions.d.ts.map +1 -0
- package/dist/engines/github-actions.js +215 -0
- package/dist/engines/github-actions.js.map +1 -0
- package/dist/engines/gitleaks.d.ts +3 -0
- package/dist/engines/gitleaks.d.ts.map +1 -0
- package/dist/engines/gitleaks.js +107 -0
- package/dist/engines/gitleaks.js.map +1 -0
- package/dist/engines/npm-audit.d.ts +3 -0
- package/dist/engines/npm-audit.d.ts.map +1 -0
- package/dist/engines/npm-audit.js +113 -0
- package/dist/engines/npm-audit.js.map +1 -0
- package/dist/engines/patterns.d.ts +3 -0
- package/dist/engines/patterns.d.ts.map +1 -0
- package/dist/engines/patterns.js +1330 -0
- package/dist/engines/patterns.js.map +1 -0
- package/dist/engines/secrets.d.ts +4 -0
- package/dist/engines/secrets.d.ts.map +1 -0
- package/dist/engines/secrets.js +260 -0
- package/dist/engines/secrets.js.map +1 -0
- package/dist/engines/semgrep.d.ts +3 -0
- package/dist/engines/semgrep.d.ts.map +1 -0
- package/dist/engines/semgrep.js +173 -0
- package/dist/engines/semgrep.js.map +1 -0
- package/dist/engines/types.d.ts +30 -0
- package/dist/engines/types.d.ts.map +1 -0
- package/dist/engines/types.js +3 -0
- package/dist/engines/types.js.map +1 -0
- package/dist/engines/url-scanner.d.ts +3 -0
- package/dist/engines/url-scanner.d.ts.map +1 -0
- package/dist/engines/url-scanner.js +469 -0
- package/dist/engines/url-scanner.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +32 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +237 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/rules/.gitkeep +0 -0
- package/dist/rules/ai-llm-security.yaml +199 -0
- package/dist/rules/api-security.yaml +489 -0
- package/dist/rules/auth-patterns.yaml +406 -0
- package/dist/rules/crypto-patterns.yaml +227 -0
- package/dist/rules/database-cloud-security.yaml +169 -0
- package/dist/rules/general-security.yaml +588 -0
- package/dist/rules/injection-patterns.yaml +318 -0
- package/dist/rules/nextjs-security.yaml +532 -0
- package/dist/rules/node-security.yaml +380 -0
- package/dist/rules/rules/.gitkeep +0 -0
- package/dist/rules/rules/ai-llm-security.yaml +199 -0
- package/dist/rules/rules/api-security.yaml +489 -0
- package/dist/rules/rules/auth-patterns.yaml +406 -0
- package/dist/rules/rules/crypto-patterns.yaml +227 -0
- package/dist/rules/rules/database-cloud-security.yaml +169 -0
- package/dist/rules/rules/general-security.yaml +588 -0
- package/dist/rules/rules/injection-patterns.yaml +318 -0
- package/dist/rules/rules/nextjs-security.yaml +532 -0
- package/dist/rules/rules/node-security.yaml +380 -0
- package/dist/rules/rules/supabase-security.yaml +387 -0
- package/dist/rules/supabase-security.yaml +387 -0
- package/dist/scanning/agents/csharp-agent.d.ts +12 -0
- package/dist/scanning/agents/csharp-agent.d.ts.map +1 -0
- package/dist/scanning/agents/csharp-agent.js +592 -0
- package/dist/scanning/agents/csharp-agent.js.map +1 -0
- package/dist/scanning/agents/go-agent.d.ts +14 -0
- package/dist/scanning/agents/go-agent.d.ts.map +1 -0
- package/dist/scanning/agents/go-agent.js +641 -0
- package/dist/scanning/agents/go-agent.js.map +1 -0
- package/dist/scanning/agents/java-agent.d.ts +8 -0
- package/dist/scanning/agents/java-agent.d.ts.map +1 -0
- package/dist/scanning/agents/java-agent.js +807 -0
- package/dist/scanning/agents/java-agent.js.map +1 -0
- package/dist/scanning/agents/javascript-agent.d.ts +8 -0
- package/dist/scanning/agents/javascript-agent.d.ts.map +1 -0
- package/dist/scanning/agents/javascript-agent.js +77 -0
- package/dist/scanning/agents/javascript-agent.js.map +1 -0
- package/dist/scanning/agents/mobile-agent.d.ts +8 -0
- package/dist/scanning/agents/mobile-agent.d.ts.map +1 -0
- package/dist/scanning/agents/mobile-agent.js +916 -0
- package/dist/scanning/agents/mobile-agent.js.map +1 -0
- package/dist/scanning/agents/php-agent.d.ts +8 -0
- package/dist/scanning/agents/php-agent.d.ts.map +1 -0
- package/dist/scanning/agents/php-agent.js +679 -0
- package/dist/scanning/agents/php-agent.js.map +1 -0
- package/dist/scanning/agents/python-agent.d.ts +8 -0
- package/dist/scanning/agents/python-agent.d.ts.map +1 -0
- package/dist/scanning/agents/python-agent.js +701 -0
- package/dist/scanning/agents/python-agent.js.map +1 -0
- package/dist/scanning/agents/supabase-agent.d.ts +8 -0
- package/dist/scanning/agents/supabase-agent.d.ts.map +1 -0
- package/dist/scanning/agents/supabase-agent.js +484 -0
- package/dist/scanning/agents/supabase-agent.js.map +1 -0
- package/dist/scanning/orchestrator.d.ts +29 -0
- package/dist/scanning/orchestrator.d.ts.map +1 -0
- package/dist/scanning/orchestrator.js +186 -0
- package/dist/scanning/orchestrator.js.map +1 -0
- package/dist/scanning/tech-detector.d.ts +12 -0
- package/dist/scanning/tech-detector.d.ts.map +1 -0
- package/dist/scanning/tech-detector.js +252 -0
- package/dist/scanning/tech-detector.js.map +1 -0
- package/dist/scanning/types.d.ts +87 -0
- package/dist/scanning/types.d.ts.map +1 -0
- package/dist/scanning/types.js +5 -0
- package/dist/scanning/types.js.map +1 -0
- package/dist/utils/child-process.d.ts +2 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +4 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/context-classifier.d.ts +11 -0
- package/dist/utils/context-classifier.d.ts.map +1 -0
- package/dist/utils/context-classifier.js +79 -0
- package/dist/utils/context-classifier.js.map +1 -0
- package/dist/utils/exec.d.ts +18 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +51 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/file-filter.d.ts +4 -0
- package/dist/utils/file-filter.d.ts.map +1 -0
- package/dist/utils/file-filter.js +68 -0
- package/dist/utils/file-filter.js.map +1 -0
- package/dist/utils/fs.d.ts +2 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +5 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/post-processor.d.ts +10 -0
- package/dist/utils/post-processor.d.ts.map +1 -0
- package/dist/utils/post-processor.js +183 -0
- package/dist/utils/post-processor.js.map +1 -0
- 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":"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"}
|
|
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
|