@oculum/scanner 1.0.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/dist/formatters/cli-terminal.d.ts +27 -0
- package/dist/formatters/cli-terminal.d.ts.map +1 -0
- package/dist/formatters/cli-terminal.js +412 -0
- package/dist/formatters/cli-terminal.js.map +1 -0
- package/dist/formatters/github-comment.d.ts +41 -0
- package/dist/formatters/github-comment.d.ts.map +1 -0
- package/dist/formatters/github-comment.js +306 -0
- package/dist/formatters/github-comment.js.map +1 -0
- package/dist/formatters/grouping.d.ts +52 -0
- package/dist/formatters/grouping.d.ts.map +1 -0
- package/dist/formatters/grouping.js +152 -0
- package/dist/formatters/grouping.js.map +1 -0
- package/dist/formatters/index.d.ts +9 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +35 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/vscode-diagnostic.d.ts +103 -0
- package/dist/formatters/vscode-diagnostic.d.ts.map +1 -0
- package/dist/formatters/vscode-diagnostic.js +151 -0
- package/dist/formatters/vscode-diagnostic.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +648 -0
- package/dist/index.js.map +1 -0
- package/dist/layer1/comments.d.ts +8 -0
- package/dist/layer1/comments.d.ts.map +1 -0
- package/dist/layer1/comments.js +203 -0
- package/dist/layer1/comments.js.map +1 -0
- package/dist/layer1/config-audit.d.ts +8 -0
- package/dist/layer1/config-audit.d.ts.map +1 -0
- package/dist/layer1/config-audit.js +252 -0
- package/dist/layer1/config-audit.js.map +1 -0
- package/dist/layer1/entropy.d.ts +8 -0
- package/dist/layer1/entropy.d.ts.map +1 -0
- package/dist/layer1/entropy.js +500 -0
- package/dist/layer1/entropy.js.map +1 -0
- package/dist/layer1/file-flags.d.ts +7 -0
- package/dist/layer1/file-flags.d.ts.map +1 -0
- package/dist/layer1/file-flags.js +112 -0
- package/dist/layer1/file-flags.js.map +1 -0
- package/dist/layer1/index.d.ts +36 -0
- package/dist/layer1/index.d.ts.map +1 -0
- package/dist/layer1/index.js +132 -0
- package/dist/layer1/index.js.map +1 -0
- package/dist/layer1/patterns.d.ts +8 -0
- package/dist/layer1/patterns.d.ts.map +1 -0
- package/dist/layer1/patterns.js +482 -0
- package/dist/layer1/patterns.js.map +1 -0
- package/dist/layer1/urls.d.ts +8 -0
- package/dist/layer1/urls.d.ts.map +1 -0
- package/dist/layer1/urls.js +296 -0
- package/dist/layer1/urls.js.map +1 -0
- package/dist/layer1/weak-crypto.d.ts +7 -0
- package/dist/layer1/weak-crypto.d.ts.map +1 -0
- package/dist/layer1/weak-crypto.js +291 -0
- package/dist/layer1/weak-crypto.js.map +1 -0
- package/dist/layer2/ai-agent-tools.d.ts +19 -0
- package/dist/layer2/ai-agent-tools.d.ts.map +1 -0
- package/dist/layer2/ai-agent-tools.js +528 -0
- package/dist/layer2/ai-agent-tools.js.map +1 -0
- package/dist/layer2/ai-endpoint-protection.d.ts +36 -0
- package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -0
- package/dist/layer2/ai-endpoint-protection.js +332 -0
- package/dist/layer2/ai-endpoint-protection.js.map +1 -0
- package/dist/layer2/ai-execution-sinks.d.ts +18 -0
- package/dist/layer2/ai-execution-sinks.d.ts.map +1 -0
- package/dist/layer2/ai-execution-sinks.js +496 -0
- package/dist/layer2/ai-execution-sinks.js.map +1 -0
- package/dist/layer2/ai-fingerprinting.d.ts +7 -0
- package/dist/layer2/ai-fingerprinting.d.ts.map +1 -0
- package/dist/layer2/ai-fingerprinting.js +654 -0
- package/dist/layer2/ai-fingerprinting.js.map +1 -0
- package/dist/layer2/ai-prompt-hygiene.d.ts +19 -0
- package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -0
- package/dist/layer2/ai-prompt-hygiene.js +356 -0
- package/dist/layer2/ai-prompt-hygiene.js.map +1 -0
- package/dist/layer2/ai-rag-safety.d.ts +21 -0
- package/dist/layer2/ai-rag-safety.d.ts.map +1 -0
- package/dist/layer2/ai-rag-safety.js +459 -0
- package/dist/layer2/ai-rag-safety.js.map +1 -0
- package/dist/layer2/ai-schema-validation.d.ts +25 -0
- package/dist/layer2/ai-schema-validation.d.ts.map +1 -0
- package/dist/layer2/ai-schema-validation.js +375 -0
- package/dist/layer2/ai-schema-validation.js.map +1 -0
- package/dist/layer2/auth-antipatterns.d.ts +20 -0
- package/dist/layer2/auth-antipatterns.d.ts.map +1 -0
- package/dist/layer2/auth-antipatterns.js +333 -0
- package/dist/layer2/auth-antipatterns.js.map +1 -0
- package/dist/layer2/byok-patterns.d.ts +12 -0
- package/dist/layer2/byok-patterns.d.ts.map +1 -0
- package/dist/layer2/byok-patterns.js +299 -0
- package/dist/layer2/byok-patterns.js.map +1 -0
- package/dist/layer2/dangerous-functions.d.ts +7 -0
- package/dist/layer2/dangerous-functions.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions.js +1375 -0
- package/dist/layer2/dangerous-functions.js.map +1 -0
- package/dist/layer2/data-exposure.d.ts +16 -0
- package/dist/layer2/data-exposure.d.ts.map +1 -0
- package/dist/layer2/data-exposure.js +279 -0
- package/dist/layer2/data-exposure.js.map +1 -0
- package/dist/layer2/framework-checks.d.ts +7 -0
- package/dist/layer2/framework-checks.d.ts.map +1 -0
- package/dist/layer2/framework-checks.js +388 -0
- package/dist/layer2/framework-checks.js.map +1 -0
- package/dist/layer2/index.d.ts +58 -0
- package/dist/layer2/index.d.ts.map +1 -0
- package/dist/layer2/index.js +380 -0
- package/dist/layer2/index.js.map +1 -0
- package/dist/layer2/logic-gates.d.ts +7 -0
- package/dist/layer2/logic-gates.d.ts.map +1 -0
- package/dist/layer2/logic-gates.js +182 -0
- package/dist/layer2/logic-gates.js.map +1 -0
- package/dist/layer2/risky-imports.d.ts +7 -0
- package/dist/layer2/risky-imports.d.ts.map +1 -0
- package/dist/layer2/risky-imports.js +161 -0
- package/dist/layer2/risky-imports.js.map +1 -0
- package/dist/layer2/variables.d.ts +8 -0
- package/dist/layer2/variables.d.ts.map +1 -0
- package/dist/layer2/variables.js +152 -0
- package/dist/layer2/variables.js.map +1 -0
- package/dist/layer3/anthropic.d.ts +83 -0
- package/dist/layer3/anthropic.d.ts.map +1 -0
- package/dist/layer3/anthropic.js +1745 -0
- package/dist/layer3/anthropic.js.map +1 -0
- package/dist/layer3/index.d.ts +24 -0
- package/dist/layer3/index.d.ts.map +1 -0
- package/dist/layer3/index.js +119 -0
- package/dist/layer3/index.js.map +1 -0
- package/dist/layer3/openai.d.ts +25 -0
- package/dist/layer3/openai.d.ts.map +1 -0
- package/dist/layer3/openai.js +238 -0
- package/dist/layer3/openai.js.map +1 -0
- package/dist/layer3/package-check.d.ts +63 -0
- package/dist/layer3/package-check.d.ts.map +1 -0
- package/dist/layer3/package-check.js +508 -0
- package/dist/layer3/package-check.js.map +1 -0
- package/dist/modes/incremental.d.ts +66 -0
- package/dist/modes/incremental.d.ts.map +1 -0
- package/dist/modes/incremental.js +200 -0
- package/dist/modes/incremental.js.map +1 -0
- package/dist/tiers.d.ts +125 -0
- package/dist/tiers.d.ts.map +1 -0
- package/dist/tiers.js +234 -0
- package/dist/tiers.js.map +1 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/auth-helper-detector.d.ts +56 -0
- package/dist/utils/auth-helper-detector.d.ts.map +1 -0
- package/dist/utils/auth-helper-detector.js +360 -0
- package/dist/utils/auth-helper-detector.js.map +1 -0
- package/dist/utils/context-helpers.d.ts +96 -0
- package/dist/utils/context-helpers.d.ts.map +1 -0
- package/dist/utils/context-helpers.js +493 -0
- package/dist/utils/context-helpers.js.map +1 -0
- package/dist/utils/diff-detector.d.ts +53 -0
- package/dist/utils/diff-detector.d.ts.map +1 -0
- package/dist/utils/diff-detector.js +104 -0
- package/dist/utils/diff-detector.js.map +1 -0
- package/dist/utils/diff-parser.d.ts +80 -0
- package/dist/utils/diff-parser.d.ts.map +1 -0
- package/dist/utils/diff-parser.js +202 -0
- package/dist/utils/diff-parser.js.map +1 -0
- package/dist/utils/imported-auth-detector.d.ts +37 -0
- package/dist/utils/imported-auth-detector.d.ts.map +1 -0
- package/dist/utils/imported-auth-detector.js +251 -0
- package/dist/utils/imported-auth-detector.js.map +1 -0
- package/dist/utils/middleware-detector.d.ts +55 -0
- package/dist/utils/middleware-detector.d.ts.map +1 -0
- package/dist/utils/middleware-detector.js +260 -0
- package/dist/utils/middleware-detector.js.map +1 -0
- package/dist/utils/oauth-flow-detector.d.ts +41 -0
- package/dist/utils/oauth-flow-detector.d.ts.map +1 -0
- package/dist/utils/oauth-flow-detector.js +202 -0
- package/dist/utils/oauth-flow-detector.js.map +1 -0
- package/dist/utils/path-exclusions.d.ts +55 -0
- package/dist/utils/path-exclusions.d.ts.map +1 -0
- package/dist/utils/path-exclusions.js +222 -0
- package/dist/utils/path-exclusions.js.map +1 -0
- package/dist/utils/project-context-builder.d.ts +119 -0
- package/dist/utils/project-context-builder.d.ts.map +1 -0
- package/dist/utils/project-context-builder.js +534 -0
- package/dist/utils/project-context-builder.js.map +1 -0
- package/dist/utils/registry-clients.d.ts +93 -0
- package/dist/utils/registry-clients.d.ts.map +1 -0
- package/dist/utils/registry-clients.js +273 -0
- package/dist/utils/registry-clients.js.map +1 -0
- package/dist/utils/trpc-analyzer.d.ts +78 -0
- package/dist/utils/trpc-analyzer.d.ts.map +1 -0
- package/dist/utils/trpc-analyzer.js +297 -0
- package/dist/utils/trpc-analyzer.js.map +1 -0
- package/package.json +45 -0
- package/src/__tests__/benchmark/fixtures/false-positives.ts +227 -0
- package/src/__tests__/benchmark/fixtures/index.ts +68 -0
- package/src/__tests__/benchmark/fixtures/layer1/config-audit.ts +364 -0
- package/src/__tests__/benchmark/fixtures/layer1/hardcoded-secrets.ts +173 -0
- package/src/__tests__/benchmark/fixtures/layer1/high-entropy.ts +234 -0
- package/src/__tests__/benchmark/fixtures/layer1/index.ts +31 -0
- package/src/__tests__/benchmark/fixtures/layer1/sensitive-urls.ts +90 -0
- package/src/__tests__/benchmark/fixtures/layer1/weak-crypto.ts +197 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-agent-tools.ts +170 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-endpoint-protection.ts +418 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-execution-sinks.ts +189 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-fingerprinting.ts +316 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-prompt-hygiene.ts +178 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-rag-safety.ts +184 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-schema-validation.ts +434 -0
- package/src/__tests__/benchmark/fixtures/layer2/auth-antipatterns.ts +159 -0
- package/src/__tests__/benchmark/fixtures/layer2/byok-patterns.ts +112 -0
- package/src/__tests__/benchmark/fixtures/layer2/dangerous-functions.ts +246 -0
- package/src/__tests__/benchmark/fixtures/layer2/data-exposure.ts +168 -0
- package/src/__tests__/benchmark/fixtures/layer2/framework-checks.ts +346 -0
- package/src/__tests__/benchmark/fixtures/layer2/index.ts +67 -0
- package/src/__tests__/benchmark/fixtures/layer2/injection-vulnerabilities.ts +239 -0
- package/src/__tests__/benchmark/fixtures/layer2/logic-gates.ts +246 -0
- package/src/__tests__/benchmark/fixtures/layer2/risky-imports.ts +231 -0
- package/src/__tests__/benchmark/fixtures/layer2/variables.ts +167 -0
- package/src/__tests__/benchmark/index.ts +29 -0
- package/src/__tests__/benchmark/run-benchmark.ts +144 -0
- package/src/__tests__/benchmark/run-depth-validation.ts +206 -0
- package/src/__tests__/benchmark/run-real-world-test.ts +243 -0
- package/src/__tests__/benchmark/security-benchmark-script.ts +1737 -0
- package/src/__tests__/benchmark/tier-integration-script.ts +177 -0
- package/src/__tests__/benchmark/types.ts +144 -0
- package/src/__tests__/benchmark/utils/test-runner.ts +475 -0
- package/src/__tests__/regression/known-false-positives.test.ts +467 -0
- package/src/__tests__/snapshots/__snapshots__/scan-depth.test.ts.snap +178 -0
- package/src/__tests__/snapshots/scan-depth.test.ts +258 -0
- package/src/__tests__/validation/analyze-results.ts +542 -0
- package/src/__tests__/validation/extract-for-triage.ts +146 -0
- package/src/__tests__/validation/fp-deep-analysis.ts +327 -0
- package/src/__tests__/validation/run-validation.ts +364 -0
- package/src/__tests__/validation/triage-template.md +132 -0
- package/src/formatters/cli-terminal.ts +446 -0
- package/src/formatters/github-comment.ts +382 -0
- package/src/formatters/grouping.ts +190 -0
- package/src/formatters/index.ts +47 -0
- package/src/formatters/vscode-diagnostic.ts +243 -0
- package/src/index.ts +823 -0
- package/src/layer1/comments.ts +218 -0
- package/src/layer1/config-audit.ts +289 -0
- package/src/layer1/entropy.ts +583 -0
- package/src/layer1/file-flags.ts +127 -0
- package/src/layer1/index.ts +181 -0
- package/src/layer1/patterns.ts +516 -0
- package/src/layer1/urls.ts +334 -0
- package/src/layer1/weak-crypto.ts +328 -0
- package/src/layer2/ai-agent-tools.ts +601 -0
- package/src/layer2/ai-endpoint-protection.ts +387 -0
- package/src/layer2/ai-execution-sinks.ts +580 -0
- package/src/layer2/ai-fingerprinting.ts +758 -0
- package/src/layer2/ai-prompt-hygiene.ts +411 -0
- package/src/layer2/ai-rag-safety.ts +511 -0
- package/src/layer2/ai-schema-validation.ts +421 -0
- package/src/layer2/auth-antipatterns.ts +394 -0
- package/src/layer2/byok-patterns.ts +336 -0
- package/src/layer2/dangerous-functions.ts +1563 -0
- package/src/layer2/data-exposure.ts +315 -0
- package/src/layer2/framework-checks.ts +433 -0
- package/src/layer2/index.ts +473 -0
- package/src/layer2/logic-gates.ts +206 -0
- package/src/layer2/risky-imports.ts +186 -0
- package/src/layer2/variables.ts +166 -0
- package/src/layer3/anthropic.ts +2030 -0
- package/src/layer3/index.ts +130 -0
- package/src/layer3/package-check.ts +604 -0
- package/src/modes/incremental.ts +293 -0
- package/src/tiers.ts +318 -0
- package/src/types.ts +284 -0
- package/src/utils/auth-helper-detector.ts +443 -0
- package/src/utils/context-helpers.ts +535 -0
- package/src/utils/diff-detector.ts +135 -0
- package/src/utils/diff-parser.ts +272 -0
- package/src/utils/imported-auth-detector.ts +320 -0
- package/src/utils/middleware-detector.ts +333 -0
- package/src/utils/oauth-flow-detector.ts +246 -0
- package/src/utils/path-exclusions.ts +266 -0
- package/src/utils/project-context-builder.ts +707 -0
- package/src/utils/registry-clients.ts +351 -0
- package/src/utils/trpc-analyzer.ts +382 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Incremental Scan Mode
|
|
4
|
+
* Optimized scanning for PR workflows - only scan changed files and surface relevant findings
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.runIncrementalScan = runIncrementalScan;
|
|
8
|
+
exports.createPRScanConfig = createPRScanConfig;
|
|
9
|
+
exports.formatIncrementalForPR = formatIncrementalForPR;
|
|
10
|
+
const layer1_1 = require("../layer1");
|
|
11
|
+
const layer2_1 = require("../layer2");
|
|
12
|
+
const diff_parser_1 = require("../utils/diff-parser");
|
|
13
|
+
const middleware_detector_1 = require("../utils/middleware-detector");
|
|
14
|
+
/**
|
|
15
|
+
* Run an incremental scan optimized for PR workflows
|
|
16
|
+
*
|
|
17
|
+
* This scans:
|
|
18
|
+
* 1. All changed files (added + modified)
|
|
19
|
+
* 2. Files that import changed files (for context)
|
|
20
|
+
* 3. Middleware files (for auth context)
|
|
21
|
+
*
|
|
22
|
+
* And only surfaces findings on/near changed lines.
|
|
23
|
+
*/
|
|
24
|
+
async function runIncrementalScan(allFiles, options) {
|
|
25
|
+
const startTime = Date.now();
|
|
26
|
+
const { diffContent, changedFiles, strictLineMatching = false, contextWindow = 5, markAsIntroduced = true, previousFindings = [], } = options;
|
|
27
|
+
// Parse diff or file list to get changed files
|
|
28
|
+
let diffs;
|
|
29
|
+
if (diffContent) {
|
|
30
|
+
diffs = (0, diff_parser_1.parseDiff)(diffContent, contextWindow);
|
|
31
|
+
}
|
|
32
|
+
else if (changedFiles && changedFiles.length > 0) {
|
|
33
|
+
diffs = (0, diff_parser_1.parseChangedFileList)(changedFiles);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// No diff info - scan everything but don't filter
|
|
37
|
+
console.log('[Incremental] No diff info provided, scanning all files');
|
|
38
|
+
diffs = new Map();
|
|
39
|
+
}
|
|
40
|
+
const changedPaths = (0, diff_parser_1.getChangedFilePaths)(diffs);
|
|
41
|
+
console.log(`[Incremental] Changed files: ${changedPaths.length}`);
|
|
42
|
+
// Build file index for import resolution
|
|
43
|
+
const fileIndex = new Map();
|
|
44
|
+
for (const file of allFiles) {
|
|
45
|
+
fileIndex.set(file.path, file);
|
|
46
|
+
}
|
|
47
|
+
// Determine which files to scan
|
|
48
|
+
const filesToScan = [];
|
|
49
|
+
const scannedPaths = new Set();
|
|
50
|
+
// 1. Add all changed files
|
|
51
|
+
for (const path of changedPaths) {
|
|
52
|
+
const file = fileIndex.get(path);
|
|
53
|
+
if (file && !scannedPaths.has(path)) {
|
|
54
|
+
filesToScan.push(file);
|
|
55
|
+
scannedPaths.add(path);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 2. Add files that import changed files (for context)
|
|
59
|
+
// This helps detect issues where changes break dependencies
|
|
60
|
+
const importers = findImporters(allFiles, changedPaths);
|
|
61
|
+
for (const path of importers) {
|
|
62
|
+
if (!scannedPaths.has(path)) {
|
|
63
|
+
const file = fileIndex.get(path);
|
|
64
|
+
if (file) {
|
|
65
|
+
filesToScan.push(file);
|
|
66
|
+
scannedPaths.add(path);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// 3. Always include middleware files for auth context
|
|
71
|
+
const middlewareFile = allFiles.find(f => f.path.includes('middleware.ts') ||
|
|
72
|
+
f.path.includes('middleware.js'));
|
|
73
|
+
if (middlewareFile && !scannedPaths.has(middlewareFile.path)) {
|
|
74
|
+
filesToScan.push(middlewareFile);
|
|
75
|
+
scannedPaths.add(middlewareFile.path);
|
|
76
|
+
}
|
|
77
|
+
console.log(`[Incremental] Scanning ${filesToScan.length} files (${changedPaths.length} changed + ${importers.size} importers)`);
|
|
78
|
+
// Detect auth middleware from ALL files (for context)
|
|
79
|
+
const middlewareConfig = (0, middleware_detector_1.detectGlobalAuthMiddleware)(allFiles);
|
|
80
|
+
// Run Layer 1 + Layer 2 on selected files
|
|
81
|
+
const layer1Result = await (0, layer1_1.runLayer1Scan)(filesToScan);
|
|
82
|
+
const layer2Result = await (0, layer2_1.runLayer2Scan)(filesToScan, { middlewareConfig });
|
|
83
|
+
let allFindings = [...layer1Result.vulnerabilities, ...layer2Result.vulnerabilities];
|
|
84
|
+
// Filter to only findings on/near changed lines
|
|
85
|
+
if (diffs.size > 0) {
|
|
86
|
+
const beforeFilter = allFindings.length;
|
|
87
|
+
allFindings = (0, diff_parser_1.filterToChangedLines)(allFindings, diffs, { strictMode: strictLineMatching });
|
|
88
|
+
console.log(`[Incremental] Filtered findings: ${beforeFilter} → ${allFindings.length} (on/near changed lines)`);
|
|
89
|
+
}
|
|
90
|
+
// Mark findings as introduced and separate pre-existing
|
|
91
|
+
const introduced = [];
|
|
92
|
+
const preExisting = [];
|
|
93
|
+
if (previousFindings.length > 0) {
|
|
94
|
+
// Create fingerprints for previous findings
|
|
95
|
+
const previousFingerprints = new Set(previousFindings.map(f => `${f.filePath}:${f.lineNumber}:${f.category}`));
|
|
96
|
+
for (const finding of allFindings) {
|
|
97
|
+
const fingerprint = `${finding.filePath}:${finding.lineNumber}:${finding.category}`;
|
|
98
|
+
if (previousFingerprints.has(fingerprint)) {
|
|
99
|
+
preExisting.push(finding);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (markAsIntroduced) {
|
|
103
|
+
finding.validationNotes = (finding.validationNotes || '') + ' [Introduced in this PR]';
|
|
104
|
+
}
|
|
105
|
+
introduced.push(finding);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// No previous findings - all are "introduced"
|
|
111
|
+
introduced.push(...allFindings);
|
|
112
|
+
}
|
|
113
|
+
const duration = Date.now() - startTime;
|
|
114
|
+
console.log(`[Incremental] Scan completed in ${duration}ms: ${introduced.length} new, ${preExisting.length} pre-existing`);
|
|
115
|
+
return {
|
|
116
|
+
findings: allFindings,
|
|
117
|
+
introduced,
|
|
118
|
+
preExisting,
|
|
119
|
+
filesScanned: filesToScan.length,
|
|
120
|
+
filesChanged: changedPaths.length,
|
|
121
|
+
diffs,
|
|
122
|
+
duration,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find files that import any of the changed files
|
|
127
|
+
*/
|
|
128
|
+
function findImporters(allFiles, changedPaths) {
|
|
129
|
+
const importers = new Set();
|
|
130
|
+
// Create patterns to match imports
|
|
131
|
+
const importPatterns = changedPaths.map(path => {
|
|
132
|
+
// Remove extension for import matching
|
|
133
|
+
const withoutExt = path.replace(/\.[^/.]+$/, '');
|
|
134
|
+
// Get just the filename without path for relative imports
|
|
135
|
+
const filename = withoutExt.split('/').pop() || '';
|
|
136
|
+
return { fullPath: withoutExt, filename };
|
|
137
|
+
});
|
|
138
|
+
for (const file of allFiles) {
|
|
139
|
+
// Skip if this file is already in changed paths
|
|
140
|
+
if (changedPaths.includes(file.path))
|
|
141
|
+
continue;
|
|
142
|
+
// Check if this file imports any changed file
|
|
143
|
+
for (const { fullPath, filename } of importPatterns) {
|
|
144
|
+
// Match various import patterns
|
|
145
|
+
const importRegex = new RegExp(`(?:import|require)\\s*(?:\\([^)]*|[^;]*from\\s*)['"]` +
|
|
146
|
+
`(?:\\.{0,2}/)?(?:${escapeRegex(fullPath)}|[^'"]*/${escapeRegex(filename)})['"]`, 'i');
|
|
147
|
+
if (importRegex.test(file.content)) {
|
|
148
|
+
importers.add(file.path);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return importers;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Escape special regex characters
|
|
157
|
+
*/
|
|
158
|
+
function escapeRegex(str) {
|
|
159
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Create a PR-optimized scan config
|
|
163
|
+
*/
|
|
164
|
+
function createPRScanConfig(changedFiles, options = {}) {
|
|
165
|
+
return {
|
|
166
|
+
mode: 'incremental',
|
|
167
|
+
changedFiles,
|
|
168
|
+
skipAIValidation: false, // Use AI for validation
|
|
169
|
+
skipLayer3: true, // Skip deep analysis for speed
|
|
170
|
+
maxAIValidationFiles: 20,
|
|
171
|
+
maxLayer3Files: 0,
|
|
172
|
+
scanDepth: 'cheap', // Fast feedback for PRs
|
|
173
|
+
...options,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Format incremental scan result for PR comment
|
|
178
|
+
*/
|
|
179
|
+
function formatIncrementalForPR(result) {
|
|
180
|
+
const blocking = result.introduced.filter(f => f.severity === 'critical' || f.severity === 'high');
|
|
181
|
+
let summary;
|
|
182
|
+
if (result.introduced.length === 0) {
|
|
183
|
+
summary = `✅ No new security issues introduced in this PR`;
|
|
184
|
+
}
|
|
185
|
+
else if (blocking.length > 0) {
|
|
186
|
+
summary = `🚨 ${blocking.length} blocking issue${blocking.length === 1 ? '' : 's'} introduced`;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
summary = `⚠️ ${result.introduced.length} new issue${result.introduced.length === 1 ? '' : 's'} to review`;
|
|
190
|
+
}
|
|
191
|
+
if (result.preExisting.length > 0) {
|
|
192
|
+
summary += ` (${result.preExisting.length} pre-existing)`;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
summary,
|
|
196
|
+
hasNewIssues: result.introduced.length > 0,
|
|
197
|
+
blockingIssues: blocking.length,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=incremental.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental.js","sourceRoot":"","sources":["../../src/modes/incremental.ts"],"names":[],"mappings":"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"}
|
package/dist/tiers.d.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detector Tier System
|
|
3
|
+
*
|
|
4
|
+
* Provides a shared language for "how much we trust this detector" so we can:
|
|
5
|
+
* - Filter findings in runScan by tier + depth
|
|
6
|
+
* - Log tier breakdowns for tuning
|
|
7
|
+
* - Route AI validation budget toward Tier B
|
|
8
|
+
*
|
|
9
|
+
* Security reasoning:
|
|
10
|
+
* - Makes it explicit which detectors are safe to expose in cheap scans
|
|
11
|
+
* - Avoids "accidental promotion" of an experimental heuristic to production output
|
|
12
|
+
*/
|
|
13
|
+
import type { VulnerabilityCategory } from './types';
|
|
14
|
+
/**
|
|
15
|
+
* Detector tiers control visibility and trust level:
|
|
16
|
+
*
|
|
17
|
+
* - core: High-precision SAST + core AI-safety detectors. Visible in all scan depths.
|
|
18
|
+
* - ai_assisted: Context-heavy heuristics that need AI validation. Shown in validated/deep.
|
|
19
|
+
* - experimental: High-noise signals used only for internal scoring/AI hints. Hidden from users.
|
|
20
|
+
*/
|
|
21
|
+
export type DetectorTier = 'core' | 'ai_assisted' | 'experimental';
|
|
22
|
+
/**
|
|
23
|
+
* Tier statistics for logging and analysis
|
|
24
|
+
*/
|
|
25
|
+
export interface TierStats {
|
|
26
|
+
core: number;
|
|
27
|
+
ai_assisted: number;
|
|
28
|
+
experimental: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Layer 1 detector names (internal identifiers matching detector function names)
|
|
32
|
+
*/
|
|
33
|
+
export type Layer1DetectorName = 'known_secrets' | 'weak_crypto' | 'sensitive_urls' | 'entropy' | 'config_audit' | 'file_flags' | 'ai_comments';
|
|
34
|
+
/**
|
|
35
|
+
* Layer 1 tier assignments
|
|
36
|
+
*
|
|
37
|
+
* Tier A (core):
|
|
38
|
+
* - known_secrets: Hardcoded secrets are objectively bad and high-impact
|
|
39
|
+
* - weak_crypto: Weak crypto is a classic SAST finding with clear remediation
|
|
40
|
+
* - sensitive_urls: Hardcoded webhook URLs + tokens are real data exfil vectors
|
|
41
|
+
*
|
|
42
|
+
* Tier B (ai_assisted):
|
|
43
|
+
* - entropy: Great at finding candidates, needs AI to separate real secrets from noise
|
|
44
|
+
* - config_audit: Depends on project norms; better reviewed with AI + project context
|
|
45
|
+
* - file_flags: Subjective items should be AI-triaged (except committed .env = Tier A)
|
|
46
|
+
*
|
|
47
|
+
* Tier C (experimental):
|
|
48
|
+
* - ai_comments: Not directly a vuln; belongs in separate "AI hygiene" report
|
|
49
|
+
*/
|
|
50
|
+
export declare const LAYER1_DETECTOR_TIERS: Record<Layer1DetectorName, DetectorTier>;
|
|
51
|
+
/**
|
|
52
|
+
* Mapping from vulnerability category to Layer 1 detector name
|
|
53
|
+
* Used for tier lookups when we only have the category
|
|
54
|
+
*/
|
|
55
|
+
export declare const LAYER1_CATEGORY_TO_DETECTOR: Partial<Record<VulnerabilityCategory, Layer1DetectorName>>;
|
|
56
|
+
/**
|
|
57
|
+
* Layer 2 detector names (internal identifiers matching detector function names)
|
|
58
|
+
*/
|
|
59
|
+
export type Layer2DetectorName = 'dangerous_functions' | 'byok_patterns' | 'ai_execution_sinks' | 'ai_agent_tools' | 'auth_antipatterns' | 'data_exposure' | 'ai_fingerprinting' | 'ai_prompt_hygiene' | 'logic_gates' | 'variables' | 'risky_imports' | 'framework_checks' | 'ai_rag_safety' | 'ai_endpoint_protection' | 'ai_schema_validation';
|
|
60
|
+
/**
|
|
61
|
+
* Layer 2 tier assignments
|
|
62
|
+
*
|
|
63
|
+
* Tier A (core) - High-precision, high-risk, clear remediation:
|
|
64
|
+
* - dangerous_functions: Classic injection footholds (eval, exec, unsafe SQL)
|
|
65
|
+
* - byok_patterns: Storing/logging BYOK is critical AI-era customer trust risk
|
|
66
|
+
* - ai_execution_sinks: Core to Oculum's AI story; LLM output as code/commands
|
|
67
|
+
* - ai_agent_tools: Over-permissive tools are central AI alignment problem
|
|
68
|
+
*
|
|
69
|
+
* Tier B (ai_assisted) - Context-heavy, need AI validation:
|
|
70
|
+
* - auth_antipatterns: Very context-dependent; needs middleware awareness
|
|
71
|
+
* - data_exposure: Logging queries/user IDs is often acceptable but context-specific
|
|
72
|
+
* - ai_fingerprinting: TypeScript 'any' at trust boundaries is risk indicator, not vuln
|
|
73
|
+
* - ai_prompt_hygiene: Needs semantic understanding of prompt design
|
|
74
|
+
*
|
|
75
|
+
* Tier C (experimental) - High-noise, internal use only:
|
|
76
|
+
* - logic_gates: Many hits with limited actionable signal
|
|
77
|
+
* - variables: Generic token/password variable names - too generic
|
|
78
|
+
* - risky_imports: Most imports are fine; keep tiny whitelist if proved valuable
|
|
79
|
+
* - framework_checks: Many findings are style/low-risk; prone to noisy lint
|
|
80
|
+
*/
|
|
81
|
+
export declare const LAYER2_DETECTOR_TIERS: Record<Layer2DetectorName, DetectorTier>;
|
|
82
|
+
/**
|
|
83
|
+
* Mapping from vulnerability category to Layer 2 detector name
|
|
84
|
+
* Used for tier lookups when we only have the category
|
|
85
|
+
*
|
|
86
|
+
* NOTE: Some categories are used by multiple detectors:
|
|
87
|
+
* - ai_pattern: used by ai-fingerprinting (Tier B), byok-patterns (Tier A), dangerous-functions (Tier A)
|
|
88
|
+
* - insecure_config: used by config-audit (L1 Tier B), framework-checks (L2 Tier C)
|
|
89
|
+
*
|
|
90
|
+
* For ambiguous categories, we use the most conservative (highest trust) tier mapping.
|
|
91
|
+
* When category alone isn't sufficient, the orchestrator can use detector-specific tracking.
|
|
92
|
+
*/
|
|
93
|
+
export declare const LAYER2_CATEGORY_TO_DETECTOR: Partial<Record<VulnerabilityCategory, Layer2DetectorName>>;
|
|
94
|
+
/**
|
|
95
|
+
* Get the tier for a vulnerability based on its category and layer
|
|
96
|
+
*/
|
|
97
|
+
export declare function getTierForCategory(category: VulnerabilityCategory, layer: 1 | 2 | 3): DetectorTier;
|
|
98
|
+
/**
|
|
99
|
+
* Get tier for a Layer 1 detector by name
|
|
100
|
+
*/
|
|
101
|
+
export declare function getLayer1DetectorTier(detector: Layer1DetectorName): DetectorTier;
|
|
102
|
+
/**
|
|
103
|
+
* Get tier for a Layer 2 detector by name
|
|
104
|
+
*/
|
|
105
|
+
export declare function getLayer2DetectorTier(detector: Layer2DetectorName): DetectorTier;
|
|
106
|
+
/**
|
|
107
|
+
* Check if a tier should be visible at a given scan depth
|
|
108
|
+
*/
|
|
109
|
+
export declare function isTierVisibleAtDepth(tier: DetectorTier, depth: 'cheap' | 'validated' | 'deep'): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Check if a tier should go through AI validation at a given scan depth
|
|
112
|
+
*/
|
|
113
|
+
export declare function shouldValidateWithAI(tier: DetectorTier, depth: 'cheap' | 'validated' | 'deep'): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Compute tier statistics from an array of vulnerabilities
|
|
116
|
+
*/
|
|
117
|
+
export declare function computeTierStats(vulnerabilities: Array<{
|
|
118
|
+
category: VulnerabilityCategory;
|
|
119
|
+
layer: 1 | 2 | 3;
|
|
120
|
+
}>): TierStats;
|
|
121
|
+
/**
|
|
122
|
+
* Format tier stats for logging
|
|
123
|
+
*/
|
|
124
|
+
export declare function formatTierStats(stats: TierStats): string;
|
|
125
|
+
//# sourceMappingURL=tiers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tiers.d.ts","sourceRoot":"","sources":["../src/tiers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,CAAA;AAElE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB;AAMD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,SAAS,GACT,cAAc,GACd,YAAY,GACZ,aAAa,CAAA;AAEjB;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAQ1E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CASlG,CAAA;AAMD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,qBAAqB,GACrB,eAAe,GACf,oBAAoB,GACpB,gBAAgB,GAChB,mBAAmB,GACnB,eAAe,GACf,mBAAmB,GACnB,mBAAmB,GACnB,aAAa,GACb,WAAW,GACX,eAAe,GACf,kBAAkB,GAElB,eAAe,GACf,wBAAwB,GACxB,sBAAsB,CAAA;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAuB1E,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAkClG,CAAA;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GACf,YAAY,CAoBd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,YAAY,CAEhF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,YAAY,CAEhF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GACpC,OAAO,CAYT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GACpC,OAAO,CAUT;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,eAAe,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,GAC5E,SAAS,CAaX;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAExD"}
|
package/dist/tiers.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Detector Tier System
|
|
4
|
+
*
|
|
5
|
+
* Provides a shared language for "how much we trust this detector" so we can:
|
|
6
|
+
* - Filter findings in runScan by tier + depth
|
|
7
|
+
* - Log tier breakdowns for tuning
|
|
8
|
+
* - Route AI validation budget toward Tier B
|
|
9
|
+
*
|
|
10
|
+
* Security reasoning:
|
|
11
|
+
* - Makes it explicit which detectors are safe to expose in cheap scans
|
|
12
|
+
* - Avoids "accidental promotion" of an experimental heuristic to production output
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.LAYER2_CATEGORY_TO_DETECTOR = exports.LAYER2_DETECTOR_TIERS = exports.LAYER1_CATEGORY_TO_DETECTOR = exports.LAYER1_DETECTOR_TIERS = void 0;
|
|
16
|
+
exports.getTierForCategory = getTierForCategory;
|
|
17
|
+
exports.getLayer1DetectorTier = getLayer1DetectorTier;
|
|
18
|
+
exports.getLayer2DetectorTier = getLayer2DetectorTier;
|
|
19
|
+
exports.isTierVisibleAtDepth = isTierVisibleAtDepth;
|
|
20
|
+
exports.shouldValidateWithAI = shouldValidateWithAI;
|
|
21
|
+
exports.computeTierStats = computeTierStats;
|
|
22
|
+
exports.formatTierStats = formatTierStats;
|
|
23
|
+
/**
|
|
24
|
+
* Layer 1 tier assignments
|
|
25
|
+
*
|
|
26
|
+
* Tier A (core):
|
|
27
|
+
* - known_secrets: Hardcoded secrets are objectively bad and high-impact
|
|
28
|
+
* - weak_crypto: Weak crypto is a classic SAST finding with clear remediation
|
|
29
|
+
* - sensitive_urls: Hardcoded webhook URLs + tokens are real data exfil vectors
|
|
30
|
+
*
|
|
31
|
+
* Tier B (ai_assisted):
|
|
32
|
+
* - entropy: Great at finding candidates, needs AI to separate real secrets from noise
|
|
33
|
+
* - config_audit: Depends on project norms; better reviewed with AI + project context
|
|
34
|
+
* - file_flags: Subjective items should be AI-triaged (except committed .env = Tier A)
|
|
35
|
+
*
|
|
36
|
+
* Tier C (experimental):
|
|
37
|
+
* - ai_comments: Not directly a vuln; belongs in separate "AI hygiene" report
|
|
38
|
+
*/
|
|
39
|
+
exports.LAYER1_DETECTOR_TIERS = {
|
|
40
|
+
known_secrets: 'core',
|
|
41
|
+
weak_crypto: 'core',
|
|
42
|
+
sensitive_urls: 'core',
|
|
43
|
+
entropy: 'ai_assisted',
|
|
44
|
+
config_audit: 'ai_assisted',
|
|
45
|
+
file_flags: 'ai_assisted', // Mixed: committed .env is effectively core
|
|
46
|
+
ai_comments: 'experimental',
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Mapping from vulnerability category to Layer 1 detector name
|
|
50
|
+
* Used for tier lookups when we only have the category
|
|
51
|
+
*/
|
|
52
|
+
exports.LAYER1_CATEGORY_TO_DETECTOR = {
|
|
53
|
+
hardcoded_secret: 'known_secrets',
|
|
54
|
+
weak_crypto: 'weak_crypto',
|
|
55
|
+
sensitive_url: 'sensitive_urls',
|
|
56
|
+
high_entropy_string: 'entropy',
|
|
57
|
+
insecure_config: 'config_audit',
|
|
58
|
+
root_container: 'config_audit',
|
|
59
|
+
dangerous_file: 'file_flags',
|
|
60
|
+
ai_pattern: 'ai_comments', // AI comment patterns detected in Layer 1
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Layer 2 tier assignments
|
|
64
|
+
*
|
|
65
|
+
* Tier A (core) - High-precision, high-risk, clear remediation:
|
|
66
|
+
* - dangerous_functions: Classic injection footholds (eval, exec, unsafe SQL)
|
|
67
|
+
* - byok_patterns: Storing/logging BYOK is critical AI-era customer trust risk
|
|
68
|
+
* - ai_execution_sinks: Core to Oculum's AI story; LLM output as code/commands
|
|
69
|
+
* - ai_agent_tools: Over-permissive tools are central AI alignment problem
|
|
70
|
+
*
|
|
71
|
+
* Tier B (ai_assisted) - Context-heavy, need AI validation:
|
|
72
|
+
* - auth_antipatterns: Very context-dependent; needs middleware awareness
|
|
73
|
+
* - data_exposure: Logging queries/user IDs is often acceptable but context-specific
|
|
74
|
+
* - ai_fingerprinting: TypeScript 'any' at trust boundaries is risk indicator, not vuln
|
|
75
|
+
* - ai_prompt_hygiene: Needs semantic understanding of prompt design
|
|
76
|
+
*
|
|
77
|
+
* Tier C (experimental) - High-noise, internal use only:
|
|
78
|
+
* - logic_gates: Many hits with limited actionable signal
|
|
79
|
+
* - variables: Generic token/password variable names - too generic
|
|
80
|
+
* - risky_imports: Most imports are fine; keep tiny whitelist if proved valuable
|
|
81
|
+
* - framework_checks: Many findings are style/low-risk; prone to noisy lint
|
|
82
|
+
*/
|
|
83
|
+
exports.LAYER2_DETECTOR_TIERS = {
|
|
84
|
+
// Tier A - Core SAST / AI-safety
|
|
85
|
+
dangerous_functions: 'core',
|
|
86
|
+
byok_patterns: 'core',
|
|
87
|
+
ai_execution_sinks: 'core',
|
|
88
|
+
ai_agent_tools: 'core',
|
|
89
|
+
// Tier B - AI-assisted heuristics
|
|
90
|
+
auth_antipatterns: 'ai_assisted',
|
|
91
|
+
data_exposure: 'ai_assisted',
|
|
92
|
+
ai_fingerprinting: 'ai_assisted',
|
|
93
|
+
ai_prompt_hygiene: 'ai_assisted',
|
|
94
|
+
// Tier C - Experimental / high-noise
|
|
95
|
+
logic_gates: 'experimental',
|
|
96
|
+
variables: 'experimental',
|
|
97
|
+
risky_imports: 'experimental',
|
|
98
|
+
framework_checks: 'experimental',
|
|
99
|
+
// M5: New AI-era detectors
|
|
100
|
+
ai_rag_safety: 'core', // Tier A - Cross-tenant data access is critical
|
|
101
|
+
ai_endpoint_protection: 'core', // Tier A - Cost abuse / API exposure has clear signals
|
|
102
|
+
ai_schema_validation: 'ai_assisted', // Tier B - Context-dependent, benefits from AI validation
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Mapping from vulnerability category to Layer 2 detector name
|
|
106
|
+
* Used for tier lookups when we only have the category
|
|
107
|
+
*
|
|
108
|
+
* NOTE: Some categories are used by multiple detectors:
|
|
109
|
+
* - ai_pattern: used by ai-fingerprinting (Tier B), byok-patterns (Tier A), dangerous-functions (Tier A)
|
|
110
|
+
* - insecure_config: used by config-audit (L1 Tier B), framework-checks (L2 Tier C)
|
|
111
|
+
*
|
|
112
|
+
* For ambiguous categories, we use the most conservative (highest trust) tier mapping.
|
|
113
|
+
* When category alone isn't sufficient, the orchestrator can use detector-specific tracking.
|
|
114
|
+
*/
|
|
115
|
+
exports.LAYER2_CATEGORY_TO_DETECTOR = {
|
|
116
|
+
// Tier A categories (unambiguous)
|
|
117
|
+
dangerous_function: 'dangerous_functions',
|
|
118
|
+
sql_injection: 'dangerous_functions',
|
|
119
|
+
command_injection: 'dangerous_functions',
|
|
120
|
+
ai_unsafe_execution: 'ai_execution_sinks',
|
|
121
|
+
ai_overpermissive_tool: 'ai_agent_tools',
|
|
122
|
+
// Tier B categories
|
|
123
|
+
missing_auth: 'auth_antipatterns',
|
|
124
|
+
data_exposure: 'data_exposure',
|
|
125
|
+
ai_prompt_injection: 'ai_prompt_hygiene',
|
|
126
|
+
// ai_pattern is ambiguous - used by multiple detectors with different tiers:
|
|
127
|
+
// - ai-fingerprinting (Tier B): TypeScript 'any' at boundaries
|
|
128
|
+
// - byok-patterns (Tier A): BYOK key handling
|
|
129
|
+
// - dangerous-functions (Tier A): JSON.parse related AI patterns
|
|
130
|
+
// Default to ai_fingerprinting (Tier B) since it's most common; byok/dangerous_functions
|
|
131
|
+
// findings are usually categorized differently or handled explicitly
|
|
132
|
+
ai_pattern: 'ai_fingerprinting',
|
|
133
|
+
// Tier C categories
|
|
134
|
+
security_bypass: 'logic_gates',
|
|
135
|
+
sensitive_variable: 'variables',
|
|
136
|
+
suspicious_package: 'risky_imports',
|
|
137
|
+
cors_misconfiguration: 'framework_checks',
|
|
138
|
+
// insecure_config from framework-checks is Tier C in Layer 2
|
|
139
|
+
// (but same category from config-audit is Tier B in Layer 1 - handled by layer check)
|
|
140
|
+
insecure_config: 'framework_checks',
|
|
141
|
+
// M5: New AI-era categories
|
|
142
|
+
ai_rag_exfiltration: 'ai_rag_safety',
|
|
143
|
+
ai_endpoint_unprotected: 'ai_endpoint_protection',
|
|
144
|
+
ai_schema_mismatch: 'ai_schema_validation',
|
|
145
|
+
};
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Tier Lookup Helpers
|
|
148
|
+
// ============================================================================
|
|
149
|
+
/**
|
|
150
|
+
* Get the tier for a vulnerability based on its category and layer
|
|
151
|
+
*/
|
|
152
|
+
function getTierForCategory(category, layer) {
|
|
153
|
+
if (layer === 1) {
|
|
154
|
+
const detector = exports.LAYER1_CATEGORY_TO_DETECTOR[category];
|
|
155
|
+
if (detector) {
|
|
156
|
+
return exports.LAYER1_DETECTOR_TIERS[detector];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (layer === 2) {
|
|
160
|
+
const detector = exports.LAYER2_CATEGORY_TO_DETECTOR[category];
|
|
161
|
+
if (detector) {
|
|
162
|
+
return exports.LAYER2_DETECTOR_TIERS[detector];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Layer 3 findings are always core (AI semantic analysis)
|
|
166
|
+
if (layer === 3) {
|
|
167
|
+
return 'core';
|
|
168
|
+
}
|
|
169
|
+
// Default to ai_assisted if unmapped (safe default - will go through AI validation)
|
|
170
|
+
return 'ai_assisted';
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get tier for a Layer 1 detector by name
|
|
174
|
+
*/
|
|
175
|
+
function getLayer1DetectorTier(detector) {
|
|
176
|
+
return exports.LAYER1_DETECTOR_TIERS[detector];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get tier for a Layer 2 detector by name
|
|
180
|
+
*/
|
|
181
|
+
function getLayer2DetectorTier(detector) {
|
|
182
|
+
return exports.LAYER2_DETECTOR_TIERS[detector];
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Check if a tier should be visible at a given scan depth
|
|
186
|
+
*/
|
|
187
|
+
function isTierVisibleAtDepth(tier, depth) {
|
|
188
|
+
switch (depth) {
|
|
189
|
+
case 'cheap':
|
|
190
|
+
// Only Tier A (core) findings are visible in cheap scans
|
|
191
|
+
return tier === 'core';
|
|
192
|
+
case 'validated':
|
|
193
|
+
// Tier A always visible, Tier B visible after AI validation
|
|
194
|
+
return tier === 'core' || tier === 'ai_assisted';
|
|
195
|
+
case 'deep':
|
|
196
|
+
// Same as validated for visibility (deep adds Layer 3, not more tiers)
|
|
197
|
+
return tier === 'core' || tier === 'ai_assisted';
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if a tier should go through AI validation at a given scan depth
|
|
202
|
+
*/
|
|
203
|
+
function shouldValidateWithAI(tier, depth) {
|
|
204
|
+
// Cheap scans skip AI validation entirely
|
|
205
|
+
if (depth === 'cheap') {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
// In validated/deep, Tier B findings should go through AI validation
|
|
209
|
+
// Tier A is high-precision and doesn't need AI validation
|
|
210
|
+
// Tier C is hidden anyway
|
|
211
|
+
return tier === 'ai_assisted';
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Compute tier statistics from an array of vulnerabilities
|
|
215
|
+
*/
|
|
216
|
+
function computeTierStats(vulnerabilities) {
|
|
217
|
+
const stats = {
|
|
218
|
+
core: 0,
|
|
219
|
+
ai_assisted: 0,
|
|
220
|
+
experimental: 0,
|
|
221
|
+
};
|
|
222
|
+
for (const vuln of vulnerabilities) {
|
|
223
|
+
const tier = getTierForCategory(vuln.category, vuln.layer);
|
|
224
|
+
stats[tier]++;
|
|
225
|
+
}
|
|
226
|
+
return stats;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Format tier stats for logging
|
|
230
|
+
*/
|
|
231
|
+
function formatTierStats(stats) {
|
|
232
|
+
return `tiers={core:${stats.core},ai_assisted:${stats.ai_assisted},experimental:${stats.experimental}}`;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=tiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tiers.js","sourceRoot":"","sources":["../src/tiers.ts"],"names":[],"mappings":"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"}
|