@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,79 @@
|
|
|
1
|
+
// Context classifier — determines if a finding is in production code,
|
|
2
|
+
// test files, examples, config, rule definitions, or vendored code.
|
|
3
|
+
// Used to separate real issues from noise in scan reports.
|
|
4
|
+
// Order matters: first match wins.
|
|
5
|
+
// Use (^|\/) to match both "test/foo.ts" and "src/test/foo.ts".
|
|
6
|
+
const PATH_RULES = [
|
|
7
|
+
// Test files
|
|
8
|
+
{ pattern: /\.test\.[cm]?[tj]sx?$/, context: "test" },
|
|
9
|
+
{ pattern: /\.spec\.[cm]?[tj]sx?$/, context: "test" },
|
|
10
|
+
{ pattern: /(^|\/)__tests__\//, context: "test" },
|
|
11
|
+
{ pattern: /(^|\/)__mocks__\//, context: "test" },
|
|
12
|
+
{ pattern: /(^|\/)fixtures?\//i, context: "test" },
|
|
13
|
+
{ pattern: /(^|\/)test\//, context: "test" },
|
|
14
|
+
{ pattern: /(^|\/)tests\//, context: "test" },
|
|
15
|
+
{ pattern: /(^|\/)e2e\//, context: "test" },
|
|
16
|
+
{ pattern: /(^|\/)cypress\//, context: "test" },
|
|
17
|
+
{ pattern: /(^|\/)playwright\//, context: "test" },
|
|
18
|
+
{ pattern: /\.stories\.[tj]sx?$/, context: "test" },
|
|
19
|
+
{ pattern: /vitest\.config/, context: "test" },
|
|
20
|
+
{ pattern: /jest\.config/, context: "test" },
|
|
21
|
+
{ pattern: /playwright\.config/, context: "test" },
|
|
22
|
+
{ pattern: /setup-e2e/, context: "test" },
|
|
23
|
+
{ pattern: /setup-test/, context: "test" },
|
|
24
|
+
{ pattern: /seed\.(ts|js|sql)$/i, context: "test" },
|
|
25
|
+
{ pattern: /(^|\/)seeds?\//, context: "test" },
|
|
26
|
+
// Rule definitions and scanner engine code
|
|
27
|
+
{ pattern: /(^|\/)rules\/.*\.ya?ml$/, context: "rule" },
|
|
28
|
+
{ pattern: /\.semgrep\.ya?ml$/, context: "rule" },
|
|
29
|
+
{ pattern: /\.gitleaks\.toml$/, context: "rule" },
|
|
30
|
+
{ pattern: /worker\/src\/engines\//, context: "rule" },
|
|
31
|
+
{ pattern: /worker\/src\/scanning\//, context: "rule" },
|
|
32
|
+
// Examples and documentation
|
|
33
|
+
{ pattern: /(^|\/)content\//, context: "example" },
|
|
34
|
+
{ pattern: /(^|\/)docs\//, context: "example" },
|
|
35
|
+
{ pattern: /(^|\/)examples?\//, context: "example" },
|
|
36
|
+
{ pattern: /(^|\/)demos?\//, context: "example" },
|
|
37
|
+
{ pattern: /(^|\/)tutorials?\//, context: "example" },
|
|
38
|
+
{ pattern: /(^|\/)samples?\//, context: "example" },
|
|
39
|
+
{ pattern: /\.example\.[^/]+$/, context: "example" },
|
|
40
|
+
{ pattern: /(^|\/)messages\/.*\.json$/, context: "example" },
|
|
41
|
+
// Config, scripts, and infrastructure
|
|
42
|
+
{ pattern: /(^|\/)scripts\//, context: "config" },
|
|
43
|
+
{ pattern: /(^|\/)\.github\/workflows\//, context: "config" },
|
|
44
|
+
{ pattern: /(^|\/)\.circleci\//, context: "config" },
|
|
45
|
+
{ pattern: /\.gitlab-ci\.ya?ml$/, context: "config" },
|
|
46
|
+
{ pattern: /Jenkinsfile$/, context: "config" },
|
|
47
|
+
{ pattern: /(^|\/)infra\//, context: "config" },
|
|
48
|
+
{ pattern: /(^|\/)terraform\//, context: "config" },
|
|
49
|
+
{ pattern: /(^|\/)pulumi\//, context: "config" },
|
|
50
|
+
{ pattern: /(^|\/)supabase\/migrations\//, context: "config" },
|
|
51
|
+
{ pattern: /(^|\/)migrations\//, context: "config" },
|
|
52
|
+
{ pattern: /(^|\/)prisma\/migrations\//, context: "config" },
|
|
53
|
+
// Vendored / generated
|
|
54
|
+
{ pattern: /(^|\/)vendor\//, context: "vendored" },
|
|
55
|
+
{ pattern: /(^|\/)generated\//, context: "vendored" },
|
|
56
|
+
{ pattern: /\.gen\.[tj]sx?$/, context: "vendored" },
|
|
57
|
+
{ pattern: /\.generated\.[tj]sx?$/, context: "vendored" },
|
|
58
|
+
{ pattern: /(^|\/)dist\//, context: "vendored" },
|
|
59
|
+
{ pattern: /(^|\/)node_modules\//, context: "vendored" },
|
|
60
|
+
];
|
|
61
|
+
export function classifyContext(input) {
|
|
62
|
+
const filePath = input.file_path ?? "";
|
|
63
|
+
// No file path = URL scanner or DB rules findings = always production
|
|
64
|
+
if (!filePath)
|
|
65
|
+
return "production";
|
|
66
|
+
for (const rule of PATH_RULES) {
|
|
67
|
+
if (rule.pattern.test(filePath)) {
|
|
68
|
+
return rule.context;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return "production";
|
|
72
|
+
}
|
|
73
|
+
export function classifyFindings(findings) {
|
|
74
|
+
return findings.map((f) => ({
|
|
75
|
+
...f,
|
|
76
|
+
context: classifyContext(f),
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=context-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-classifier.js","sourceRoot":"","sources":["../../src/utils/context-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ExecResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
exitCode: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ExecOptions {
|
|
7
|
+
timeoutMs: number;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
env?: Record<string, string>;
|
|
10
|
+
maxBuffer?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Execute a command with timeout. Returns stdout/stderr/exitCode.
|
|
14
|
+
* Throws on timeout or signal kill. Does NOT throw on non-zero exit code
|
|
15
|
+
* (many tools like gitleaks/npm audit exit non-zero when they find issues).
|
|
16
|
+
*/
|
|
17
|
+
export declare function execWithTimeout(command: string, args: string[], options: ExecOptions): Promise<ExecResult>;
|
|
18
|
+
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAqDrB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Shared utility for running external tool binaries with timeout support.
|
|
2
|
+
// Uses execFile (not exec) to avoid shell injection — critical for a security product.
|
|
3
|
+
import { execFile } from "./child-process.js";
|
|
4
|
+
import { warn } from "./logger.js";
|
|
5
|
+
const DEFAULT_MAX_BUFFER = 10 * 1024 * 1024; // 10MB
|
|
6
|
+
/**
|
|
7
|
+
* Execute a command with timeout. Returns stdout/stderr/exitCode.
|
|
8
|
+
* Throws on timeout or signal kill. Does NOT throw on non-zero exit code
|
|
9
|
+
* (many tools like gitleaks/npm audit exit non-zero when they find issues).
|
|
10
|
+
*/
|
|
11
|
+
export function execWithTimeout(command, args, options) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const child = execFile(command, args, {
|
|
14
|
+
cwd: options.cwd,
|
|
15
|
+
env: options.env ? { ...process.env, ...options.env } : undefined,
|
|
16
|
+
maxBuffer: options.maxBuffer ?? DEFAULT_MAX_BUFFER,
|
|
17
|
+
timeout: 0, // We handle timeout ourselves for graceful kill
|
|
18
|
+
}, (error, stdout, stderr) => {
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
if (timedOut) {
|
|
21
|
+
return; // Already rejected by timeout handler
|
|
22
|
+
}
|
|
23
|
+
if (error && error.killed) {
|
|
24
|
+
reject(new Error(`${command} was killed by signal`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Non-zero exit code is NOT an error — tools like gitleaks exit 1 on findings
|
|
28
|
+
const exitCode = error?.code !== undefined
|
|
29
|
+
? (typeof error.code === "number" ? error.code : 1)
|
|
30
|
+
: 0;
|
|
31
|
+
resolve({ stdout, stderr, exitCode });
|
|
32
|
+
});
|
|
33
|
+
let timedOut = false;
|
|
34
|
+
const timer = setTimeout(() => {
|
|
35
|
+
timedOut = true;
|
|
36
|
+
warn(`${command} timed out after ${options.timeoutMs}ms, sending SIGTERM`);
|
|
37
|
+
child.kill("SIGTERM");
|
|
38
|
+
// Force kill after 5s if still alive
|
|
39
|
+
const forceKillTimer = setTimeout(() => {
|
|
40
|
+
if (!child.killed) {
|
|
41
|
+
warn(`${command} did not exit after SIGTERM, sending SIGKILL`);
|
|
42
|
+
child.kill("SIGKILL");
|
|
43
|
+
}
|
|
44
|
+
}, 5000);
|
|
45
|
+
forceKillTimer.unref();
|
|
46
|
+
reject(new Error(`${command} timed out after ${options.timeoutMs}ms`));
|
|
47
|
+
}, options.timeoutMs);
|
|
48
|
+
timer.unref();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,uFAAuF;AAEvF,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAenC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAEpD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,IAAc,EACd,OAAoB;IAEpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,QAAQ,CACpB,OAAO,EACP,IAAI,EACJ;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;YACjE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,kBAAkB;YAClD,OAAO,EAAE,CAAC,EAAE,gDAAgD;SAC7D,EACD,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,sCAAsC;YAChD,CAAC;YAED,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,uBAAuB,CAAC,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,8EAA8E;YAC9E,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAI,KAAK,SAAS;gBACxC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnD,CAAC,CAAC,CAAC,CAAC;YAEN,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC,CACF,CAAC;QAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,GAAG,OAAO,oBAAoB,OAAO,CAAC,SAAS,qBAAqB,CAAC,CAAC;YAC3E,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAEtB,qCAAqC;YACrC,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;gBACrC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;oBAClB,IAAI,CAAC,GAAG,OAAO,8CAA8C,CAAC,CAAC;oBAC/D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,cAAc,CAAC,KAAK,EAAE,CAAC;YAEvB,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,oBAAoB,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;QACzE,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAEtB,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-filter.d.ts","sourceRoot":"","sources":["../../src/utils/file-filter.ts"],"names":[],"mappings":"AAiCA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgBxD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ3E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUxD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const SCANNABLE_EXTENSIONS = [
|
|
2
|
+
// JavaScript / TypeScript
|
|
3
|
+
".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
|
|
4
|
+
// Languages covered by the multi-tech scan agents
|
|
5
|
+
".py", ".go", ".java", ".kt", ".kts", ".php", ".cs", ".fs",
|
|
6
|
+
".rb", ".rs", ".dart",
|
|
7
|
+
// Config / data formats (includes pyproject.toml, Cargo.toml, etc.)
|
|
8
|
+
".json", ".yaml", ".yml", ".toml", ".gradle", ".sql", ".rules",
|
|
9
|
+
".csproj", ".fsproj", ".sln",
|
|
10
|
+
".env", ".env.local", ".env.production",
|
|
11
|
+
];
|
|
12
|
+
const SCANNABLE_EXACT_FILES = [
|
|
13
|
+
".gitignore", "Dockerfile", "docker-compose.yml", "docker-compose.yaml",
|
|
14
|
+
".dockerignore", "Makefile", ".npmrc", ".yarnrc",
|
|
15
|
+
"vercel.json", "netlify.toml", "tsconfig.json",
|
|
16
|
+
".eslintrc.json", ".eslintrc.js", ".prettierrc",
|
|
17
|
+
"next.config.js", "next.config.ts", "next.config.mjs",
|
|
18
|
+
"firebase.json", "firestore.rules", "storage.rules",
|
|
19
|
+
"supabase/config.toml",
|
|
20
|
+
".env.example",
|
|
21
|
+
// Manifests the TechDetector relies on for non-JS stacks
|
|
22
|
+
"requirements.txt", "Pipfile", "go.mod", "go.sum",
|
|
23
|
+
"pom.xml", "Gemfile", "Gemfile.lock",
|
|
24
|
+
];
|
|
25
|
+
const SKIP_DIRECTORIES = [
|
|
26
|
+
"node_modules", ".next", ".git", "dist", "build", ".cache",
|
|
27
|
+
"coverage", ".nyc_output", "__pycache__", ".venv",
|
|
28
|
+
];
|
|
29
|
+
const MAX_FILE_SIZE = 500_000; // 500KB - skip very large files
|
|
30
|
+
export function isRelevantFile(filePath) {
|
|
31
|
+
// Skip hidden/build directories (allow .github for workflow scanning)
|
|
32
|
+
const parts = filePath.split("/");
|
|
33
|
+
for (const part of parts.slice(0, -1)) {
|
|
34
|
+
if (part === ".github")
|
|
35
|
+
continue; // Allow .github/workflows/
|
|
36
|
+
if (SKIP_DIRECTORIES.includes(part))
|
|
37
|
+
return false;
|
|
38
|
+
if (part.startsWith(".") && part !== ".")
|
|
39
|
+
return false; // Skip other hidden dirs
|
|
40
|
+
}
|
|
41
|
+
const fileName = parts[parts.length - 1];
|
|
42
|
+
// Check exact file matches
|
|
43
|
+
if (SCANNABLE_EXACT_FILES.includes(fileName))
|
|
44
|
+
return true;
|
|
45
|
+
// Check extensions
|
|
46
|
+
return SCANNABLE_EXTENSIONS.some(ext => fileName.endsWith(ext));
|
|
47
|
+
}
|
|
48
|
+
export function filterFiles(files) {
|
|
49
|
+
const filtered = new Map();
|
|
50
|
+
for (const [path, content] of files) {
|
|
51
|
+
if (isRelevantFile(path) && content.length <= MAX_FILE_SIZE) {
|
|
52
|
+
filtered.set(path, content);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return filtered;
|
|
56
|
+
}
|
|
57
|
+
export function getFileLanguage(filePath) {
|
|
58
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
59
|
+
const langMap = {
|
|
60
|
+
ts: "typescript", tsx: "typescript",
|
|
61
|
+
js: "javascript", jsx: "javascript", mjs: "javascript", cjs: "javascript",
|
|
62
|
+
json: "json", yaml: "yaml", yml: "yaml",
|
|
63
|
+
sql: "sql", rules: "text",
|
|
64
|
+
env: "dotenv",
|
|
65
|
+
};
|
|
66
|
+
return langMap[ext || ""] || "text";
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=file-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-filter.js","sourceRoot":"","sources":["../../src/utils/file-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,yDAAyD;AACzD,8CAA8C;AAE9C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface LogContext {
|
|
2
|
+
scanId?: string;
|
|
3
|
+
engine?: string;
|
|
4
|
+
duration?: number;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function log(message: string, context?: LogContext): void;
|
|
8
|
+
export declare function warn(message: string, context?: LogContext): void;
|
|
9
|
+
export declare function error(message: string, context?: LogContext): void;
|
|
10
|
+
export declare function debug(message: string, context?: LogContext): void;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAgBD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAE/D;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAEhE;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAEjE;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAIjE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function formatLog(level, message, context) {
|
|
2
|
+
const timestamp = new Date().toISOString();
|
|
3
|
+
const prefix = context?.scanId ? `[scan:${context.scanId}]` : "";
|
|
4
|
+
const enginePrefix = context?.engine ? `[${context.engine}]` : "";
|
|
5
|
+
const extra = context
|
|
6
|
+
? Object.entries(context)
|
|
7
|
+
.filter(([key]) => key !== "scanId" && key !== "engine")
|
|
8
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
9
|
+
.join(" ")
|
|
10
|
+
: "";
|
|
11
|
+
return `${timestamp} ${level.toUpperCase()} ${prefix}${enginePrefix} ${message}${extra ? " " + extra : ""}`;
|
|
12
|
+
}
|
|
13
|
+
export function log(message, context) {
|
|
14
|
+
console.log(formatLog("info", message, context));
|
|
15
|
+
}
|
|
16
|
+
export function warn(message, context) {
|
|
17
|
+
console.warn(formatLog("warn", message, context));
|
|
18
|
+
}
|
|
19
|
+
export function error(message, context) {
|
|
20
|
+
console.error(formatLog("error", message, context));
|
|
21
|
+
}
|
|
22
|
+
export function debug(message, context) {
|
|
23
|
+
if (process.env.DEBUG === "true") {
|
|
24
|
+
console.debug(formatLog("debug", message, context));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AASA,SAAS,SAAS,CAAC,KAAe,EAAE,OAAe,EAAE,OAAoB;IACvE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,YAAY,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,KAAK,GAAG,OAAO;QACnB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ,CAAC;aACvD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;aACxC,IAAI,CAAC,GAAG,CAAC;QACd,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,GAAG,SAAS,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,GAAG,YAAY,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC9G,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,OAAoB;IACvD,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,OAAoB;IACxD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,OAAoB;IACzD,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,OAAoB;IACzD,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FindingData } from "../engines/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Run all four post-processing steps on the aggregated findings.
|
|
4
|
+
*
|
|
5
|
+
* @param findings Deduplicated, context-classified findings from all engines.
|
|
6
|
+
* @param technologies Technology list from detectTechnologies().technologies.
|
|
7
|
+
* @returns Processed findings ready for score calculation.
|
|
8
|
+
*/
|
|
9
|
+
export declare function postProcessFindings(findings: FindingData[], technologies: string[]): FindingData[];
|
|
10
|
+
//# sourceMappingURL=post-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-processor.d.ts","sourceRoot":"","sources":["../../src/utils/post-processor.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAyMvD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,WAAW,EAAE,EACvB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,EAAE,CAMf"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// Post-processing pipeline for scan findings.
|
|
2
|
+
// Runs after all engines complete but before score calculation.
|
|
3
|
+
// Steps (in order):
|
|
4
|
+
// 1. Framework-aware suppressions — mark findings that are known framework
|
|
5
|
+
// requirements so they don't penalize the score.
|
|
6
|
+
// 2. Cross-engine deduplication — merge findings for the same root cause
|
|
7
|
+
// that survived the primary dedup (different file_path, same vuln_id).
|
|
8
|
+
// 3. Contextual notes — add description_simple for specific patterns.
|
|
9
|
+
// 4. Classification — label each finding as "actionable" or "informational".
|
|
10
|
+
// Keys are lowercased technology names as returned by detectTechnologies().
|
|
11
|
+
const FRAMEWORK_RULES = {
|
|
12
|
+
nextjs: [
|
|
13
|
+
{
|
|
14
|
+
vulnerability_id: 63,
|
|
15
|
+
title_contains: "unsafe-inline",
|
|
16
|
+
note: "Next.js App Router requires 'unsafe-inline' in script-src for hydration. This cannot be removed without breaking the framework.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
vulnerability_id: 99,
|
|
20
|
+
title_contains: "robots.txt",
|
|
21
|
+
note: "robots.txt is standard web practice and expected on production sites.",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
supabase: [
|
|
25
|
+
{
|
|
26
|
+
vulnerability_id: 67,
|
|
27
|
+
cookie_name_starts: "sb-",
|
|
28
|
+
note: "Supabase Auth manages cookie security flags through its SDK configuration.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
vulnerability_id: 68,
|
|
32
|
+
cookie_name_starts: "sb-",
|
|
33
|
+
note: "Supabase Auth cookies require client-side JavaScript access for session refresh.",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
"next-intl": [
|
|
37
|
+
{
|
|
38
|
+
vulnerability_id: 67,
|
|
39
|
+
cookie_name: "NEXT_LOCALE",
|
|
40
|
+
note: "next-intl locale cookie requires client-side JavaScript access for locale synchronization.",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
vulnerability_id: 68,
|
|
44
|
+
cookie_name: "NEXT_LOCALE",
|
|
45
|
+
note: "next-intl locale cookie requires client-side JavaScript access for locale synchronization.",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
function matchesFrameworkRule(finding, rule) {
|
|
50
|
+
if (finding.vulnerability_id !== rule.vulnerability_id)
|
|
51
|
+
return false;
|
|
52
|
+
if (rule.title_contains !== undefined) {
|
|
53
|
+
if (!finding.title.toLowerCase().includes(rule.title_contains.toLowerCase())) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (rule.cookie_name_starts !== undefined) {
|
|
58
|
+
const snippet = finding.code_snippet ?? finding.title ?? "";
|
|
59
|
+
if (!snippet.includes(rule.cookie_name_starts))
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (rule.cookie_name !== undefined) {
|
|
63
|
+
const snippet = finding.code_snippet ?? finding.title ?? "";
|
|
64
|
+
if (!snippet.includes(rule.cookie_name))
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
function applyFrameworkSuppressions(findings, technologies) {
|
|
70
|
+
// Normalize tech names to lowercase for lookup.
|
|
71
|
+
const normalizedTechs = technologies.map((t) => t.toLowerCase());
|
|
72
|
+
// Collect applicable rules based on detected technologies.
|
|
73
|
+
const applicableRules = [];
|
|
74
|
+
for (const tech of normalizedTechs) {
|
|
75
|
+
const rules = FRAMEWORK_RULES[tech];
|
|
76
|
+
if (rules) {
|
|
77
|
+
applicableRules.push(...rules);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (applicableRules.length === 0)
|
|
81
|
+
return findings;
|
|
82
|
+
return findings.map((finding) => {
|
|
83
|
+
for (const rule of applicableRules) {
|
|
84
|
+
if (matchesFrameworkRule(finding, rule)) {
|
|
85
|
+
return {
|
|
86
|
+
...finding,
|
|
87
|
+
is_framework_requirement: true,
|
|
88
|
+
framework_note: rule.note,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return finding;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Step 2: Cross-Engine Deduplication
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// The primary dedup in orchestrator.ts groups by vulnerability_id + file_path +
|
|
99
|
+
// line_number. That misses cases where two engines report the same root cause
|
|
100
|
+
// at different levels — e.g. the config engine points to next.config.ts while
|
|
101
|
+
// the URL scanner has no file_path at all. Group by vulnerability_id alone when
|
|
102
|
+
// one side lacks a file_path and keep whichever finding HAS a file_path.
|
|
103
|
+
function crossEngineDedup(findings) {
|
|
104
|
+
// Separate findings that have a file_path from those that don't.
|
|
105
|
+
const withPath = [];
|
|
106
|
+
const withoutPath = [];
|
|
107
|
+
for (const f of findings) {
|
|
108
|
+
if (f.file_path) {
|
|
109
|
+
withPath.push(f);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
withoutPath.push(f);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// For each no-path finding, check if there is already a with-path finding
|
|
116
|
+
// for the same vulnerability_id. If yes, skip the no-path finding (the
|
|
117
|
+
// with-path one is more actionable). Otherwise keep it.
|
|
118
|
+
const withPathVulnIds = new Set(withPath.map((f) => f.vulnerability_id));
|
|
119
|
+
const filteredWithoutPath = withoutPath.filter((f) => !withPathVulnIds.has(f.vulnerability_id));
|
|
120
|
+
return [...withPath, ...filteredWithoutPath];
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Step 3: Contextual Notes
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
function addContextualNotes(findings) {
|
|
126
|
+
return findings.map((finding) => {
|
|
127
|
+
// Don't overwrite an existing description_simple.
|
|
128
|
+
if (finding.description_simple)
|
|
129
|
+
return finding;
|
|
130
|
+
if (finding.is_framework_requirement && finding.framework_note) {
|
|
131
|
+
return { ...finding, description_simple: finding.framework_note };
|
|
132
|
+
}
|
|
133
|
+
if (finding.category === "headers" && finding.severity === "info") {
|
|
134
|
+
return {
|
|
135
|
+
...finding,
|
|
136
|
+
description_simple: "This is informational — no action required.",
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (finding.severity === "low" && finding.confidence === "low") {
|
|
140
|
+
return {
|
|
141
|
+
...finding,
|
|
142
|
+
description_simple: "This is a low-confidence observation. Verify manually before acting.",
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return finding;
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// Step 4: Classification
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
function classifyFindings(findings) {
|
|
152
|
+
return findings.map((finding) => {
|
|
153
|
+
let classification;
|
|
154
|
+
if (finding.is_framework_requirement) {
|
|
155
|
+
classification = "informational";
|
|
156
|
+
}
|
|
157
|
+
else if (finding.severity === "info") {
|
|
158
|
+
classification = "informational";
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
classification = "actionable";
|
|
162
|
+
}
|
|
163
|
+
return { ...finding, classification };
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Public API
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
/**
|
|
170
|
+
* Run all four post-processing steps on the aggregated findings.
|
|
171
|
+
*
|
|
172
|
+
* @param findings Deduplicated, context-classified findings from all engines.
|
|
173
|
+
* @param technologies Technology list from detectTechnologies().technologies.
|
|
174
|
+
* @returns Processed findings ready for score calculation.
|
|
175
|
+
*/
|
|
176
|
+
export function postProcessFindings(findings, technologies) {
|
|
177
|
+
const step1 = applyFrameworkSuppressions(findings, technologies);
|
|
178
|
+
const step2 = crossEngineDedup(step1);
|
|
179
|
+
const step3 = addContextualNotes(step2);
|
|
180
|
+
const step4 = classifyFindings(step3);
|
|
181
|
+
return step4;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=post-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-processor.js","sourceRoot":"","sources":["../../src/utils/post-processor.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@datahogo/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Data Hogo scan engine — 300+ security checks for JS/TS, Python, Go, Java, PHP, C#, mobile and Supabase. Runs locally.",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/datahogo/datahogo.git",
|
|
9
|
+
"directory": "packages/core"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://datahogo.com",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc && cp -R src/rules dist/rules",
|
|
29
|
+
"test": "vitest run"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"security",
|
|
33
|
+
"scanner",
|
|
34
|
+
"sast",
|
|
35
|
+
"static-analysis",
|
|
36
|
+
"vulnerability",
|
|
37
|
+
"secrets-detection"
|
|
38
|
+
],
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^20.14.0",
|
|
41
|
+
"typescript": "^5.4.0",
|
|
42
|
+
"vitest": "^1.6.0"
|
|
43
|
+
}
|
|
44
|
+
}
|