@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,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Benchmark Test Runner
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive security benchmark suite for the Oculum scanner, covering:
|
|
5
|
+
* - Traditional OWASP-style vulnerabilities
|
|
6
|
+
* - AI-specific security issues (prompt injection, unsafe execution, BYOK, etc.)
|
|
7
|
+
* - False positive scenarios (patterns that should NOT be flagged)
|
|
8
|
+
*
|
|
9
|
+
* Run with: npx tsx src/lib/scanner/__tests__/benchmark/run-benchmark.ts
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
allTestGroups,
|
|
14
|
+
falsePositiveFixtures,
|
|
15
|
+
highEntropyTests,
|
|
16
|
+
} from './fixtures'
|
|
17
|
+
import {
|
|
18
|
+
runTestFixture,
|
|
19
|
+
printTestResult,
|
|
20
|
+
computeSummary,
|
|
21
|
+
printSummary,
|
|
22
|
+
printMetrics,
|
|
23
|
+
} from './utils/test-runner'
|
|
24
|
+
import type { TestResult } from './types'
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
console.log('='.repeat(80))
|
|
28
|
+
console.log('OCULUM SECURITY BENCHMARK TEST SUITE')
|
|
29
|
+
console.log('='.repeat(80))
|
|
30
|
+
console.log('')
|
|
31
|
+
|
|
32
|
+
const results: TestResult[] = []
|
|
33
|
+
|
|
34
|
+
// ========================================
|
|
35
|
+
// LAYER 1 TESTS
|
|
36
|
+
// ========================================
|
|
37
|
+
|
|
38
|
+
console.log('\n' + 'ā'.repeat(80))
|
|
39
|
+
console.log('LAYER 1: SURFACE SCAN TESTS')
|
|
40
|
+
console.log('ā'.repeat(80))
|
|
41
|
+
|
|
42
|
+
const layer1Groups = allTestGroups.filter(g => g.layer === 1)
|
|
43
|
+
|
|
44
|
+
for (const group of layer1Groups) {
|
|
45
|
+
console.log(`\nš TIER ${group.tier} (${group.tier === 'A' ? 'Core' : 'AI-Assisted'}): ${group.name}`)
|
|
46
|
+
|
|
47
|
+
if (group.truePositives.length > 0) {
|
|
48
|
+
console.log(' Testing TRUE POSITIVES...')
|
|
49
|
+
for (const fixture of group.truePositives) {
|
|
50
|
+
const result = await runTestFixture(fixture)
|
|
51
|
+
results.push(result)
|
|
52
|
+
printTestResult(result)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (group.falseNegatives.length > 0) {
|
|
57
|
+
console.log(' Testing FALSE NEGATIVES (should NOT flag)...')
|
|
58
|
+
for (const fixture of group.falseNegatives) {
|
|
59
|
+
const result = await runTestFixture(fixture)
|
|
60
|
+
results.push(result)
|
|
61
|
+
printTestResult(result)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// High Entropy (Tier B)
|
|
67
|
+
console.log(`\nš TIER B (AI-Assisted): ${highEntropyTests.name}`)
|
|
68
|
+
console.log(' Testing TRUE POSITIVES...')
|
|
69
|
+
for (const fixture of highEntropyTests.truePositives) {
|
|
70
|
+
const result = await runTestFixture(fixture)
|
|
71
|
+
results.push(result)
|
|
72
|
+
printTestResult(result)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ========================================
|
|
76
|
+
// LAYER 2 TESTS
|
|
77
|
+
// ========================================
|
|
78
|
+
|
|
79
|
+
console.log('\n' + 'ā'.repeat(80))
|
|
80
|
+
console.log('LAYER 2: STRUCTURAL SCAN TESTS')
|
|
81
|
+
console.log('ā'.repeat(80))
|
|
82
|
+
|
|
83
|
+
const layer2Groups = allTestGroups.filter(g => g.layer === 2)
|
|
84
|
+
|
|
85
|
+
for (const group of layer2Groups) {
|
|
86
|
+
console.log(`\nš TIER ${group.tier} (${group.tier === 'A' ? 'Core' : 'AI-Assisted'}): ${group.name}`)
|
|
87
|
+
|
|
88
|
+
if (group.truePositives.length > 0) {
|
|
89
|
+
console.log(' Testing TRUE POSITIVES...')
|
|
90
|
+
for (const fixture of group.truePositives) {
|
|
91
|
+
const result = await runTestFixture(fixture)
|
|
92
|
+
results.push(result)
|
|
93
|
+
printTestResult(result)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (group.falseNegatives.length > 0) {
|
|
98
|
+
console.log(' Testing FALSE NEGATIVES (should NOT flag)...')
|
|
99
|
+
for (const fixture of group.falseNegatives) {
|
|
100
|
+
const result = await runTestFixture(fixture)
|
|
101
|
+
results.push(result)
|
|
102
|
+
printTestResult(result)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ========================================
|
|
108
|
+
// FALSE POSITIVE TESTS
|
|
109
|
+
// ========================================
|
|
110
|
+
|
|
111
|
+
console.log('\n' + 'ā'.repeat(80))
|
|
112
|
+
console.log('FALSE POSITIVE TESTS')
|
|
113
|
+
console.log('ā'.repeat(80))
|
|
114
|
+
|
|
115
|
+
for (const fixture of falsePositiveFixtures) {
|
|
116
|
+
console.log(`\nš ${fixture.name}`)
|
|
117
|
+
const result = await runTestFixture(fixture)
|
|
118
|
+
results.push(result)
|
|
119
|
+
printTestResult(result)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ========================================
|
|
123
|
+
// RESULTS SUMMARY
|
|
124
|
+
// ========================================
|
|
125
|
+
|
|
126
|
+
console.log('\n' + '='.repeat(80))
|
|
127
|
+
console.log('BENCHMARK RESULTS SUMMARY')
|
|
128
|
+
console.log('='.repeat(80))
|
|
129
|
+
|
|
130
|
+
// Compute summary with metrics
|
|
131
|
+
const summary = computeSummary(results)
|
|
132
|
+
|
|
133
|
+
// Print detailed metrics
|
|
134
|
+
printMetrics(summary.metrics)
|
|
135
|
+
|
|
136
|
+
// Print final summary
|
|
137
|
+
printSummary(summary)
|
|
138
|
+
|
|
139
|
+
// Exit with appropriate code
|
|
140
|
+
process.exit(summary.passRate === 100 ? 0 : 1)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Run the test suite
|
|
144
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan Depth Profile Validation
|
|
3
|
+
* Validates that cheap/validated/deep modes work correctly
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { runLayer1Scan } from '../../layer1'
|
|
7
|
+
import { runLayer2Scan } from '../../layer2'
|
|
8
|
+
import { getTierForCategory, isTierVisibleAtDepth, formatTierStats, computeTierStats } from '../../tiers'
|
|
9
|
+
import type { ScanFile, ScanDepth, Vulnerability } from '../../types'
|
|
10
|
+
|
|
11
|
+
// Test fixture with various vulnerability types
|
|
12
|
+
const testFile: ScanFile = {
|
|
13
|
+
path: 'src/api/test-route.ts',
|
|
14
|
+
content: `
|
|
15
|
+
// This file contains patterns from different tiers for testing
|
|
16
|
+
|
|
17
|
+
// Tier A (core): Hardcoded secret - always visible
|
|
18
|
+
const API_KEY = "sk_live_abc123def456ghi789jkl012mno345pqr678"
|
|
19
|
+
|
|
20
|
+
// Tier A (core): Dangerous function - always visible
|
|
21
|
+
export function executeQuery(input: string) {
|
|
22
|
+
return db.query(\`SELECT * FROM users WHERE id = '\${input}'\`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Tier B (ai_assisted): AI pattern - needs validation in validated/deep modes
|
|
26
|
+
// TODO: This was AI generated and needs review
|
|
27
|
+
const placeholder = "implementation goes here"
|
|
28
|
+
|
|
29
|
+
// Tier C (experimental): Should always be hidden
|
|
30
|
+
const suspiciousVar = "possibly_risky"
|
|
31
|
+
|
|
32
|
+
export async function GET() {
|
|
33
|
+
// Missing auth pattern (Tier B)
|
|
34
|
+
const data = await db.query('SELECT * FROM data')
|
|
35
|
+
return NextResponse.json(data)
|
|
36
|
+
}
|
|
37
|
+
`,
|
|
38
|
+
language: 'typescript',
|
|
39
|
+
size: 700,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Helper to classify findings by tier
|
|
43
|
+
function classifyFindings(findings: Vulnerability[]): {
|
|
44
|
+
core: Vulnerability[]
|
|
45
|
+
ai_assisted: Vulnerability[]
|
|
46
|
+
experimental: Vulnerability[]
|
|
47
|
+
} {
|
|
48
|
+
const result: {
|
|
49
|
+
core: Vulnerability[]
|
|
50
|
+
ai_assisted: Vulnerability[]
|
|
51
|
+
experimental: Vulnerability[]
|
|
52
|
+
} = { core: [], ai_assisted: [], experimental: [] }
|
|
53
|
+
|
|
54
|
+
for (const f of findings) {
|
|
55
|
+
const tier = getTierForCategory(f.category, f.layer)
|
|
56
|
+
result[tier].push(f)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function runValidation() {
|
|
63
|
+
console.log('=' .repeat(70))
|
|
64
|
+
console.log('SCAN DEPTH PROFILE VALIDATION')
|
|
65
|
+
console.log('=' .repeat(70))
|
|
66
|
+
|
|
67
|
+
// Run scans
|
|
68
|
+
console.log('\nš Running Layer 1 + Layer 2 scans...')
|
|
69
|
+
const startScan = Date.now()
|
|
70
|
+
const l1 = await runLayer1Scan([testFile])
|
|
71
|
+
const l2 = await runLayer2Scan([testFile])
|
|
72
|
+
const scanDuration = Date.now() - startScan
|
|
73
|
+
|
|
74
|
+
const allFindings = [...l1.vulnerabilities, ...l2.vulnerabilities]
|
|
75
|
+
const classified = classifyFindings(allFindings)
|
|
76
|
+
|
|
77
|
+
console.log(`\nā±ļø Scan duration: ${scanDuration}ms`)
|
|
78
|
+
console.log(`\nš Total findings: ${allFindings.length}`)
|
|
79
|
+
console.log(` Tier A (core): ${classified.core.length}`)
|
|
80
|
+
console.log(` Tier B (ai_assisted): ${classified.ai_assisted.length}`)
|
|
81
|
+
console.log(` Tier C (experimental): ${classified.experimental.length}`)
|
|
82
|
+
|
|
83
|
+
// Show tier stats
|
|
84
|
+
const tierStats = computeTierStats(
|
|
85
|
+
allFindings.map(v => ({ category: v.category, layer: v.layer }))
|
|
86
|
+
)
|
|
87
|
+
console.log(`\nš ${formatTierStats(tierStats)}`)
|
|
88
|
+
|
|
89
|
+
// Test each depth mode
|
|
90
|
+
const depths: ScanDepth[] = ['cheap', 'validated', 'deep']
|
|
91
|
+
|
|
92
|
+
console.log('\n' + '-'.repeat(70))
|
|
93
|
+
console.log('DEPTH MODE BEHAVIOR')
|
|
94
|
+
console.log('-'.repeat(70))
|
|
95
|
+
|
|
96
|
+
for (const depth of depths) {
|
|
97
|
+
console.log(`\nšļø ${depth.toUpperCase()} mode:`)
|
|
98
|
+
|
|
99
|
+
const coreVisible = isTierVisibleAtDepth('core', depth)
|
|
100
|
+
const aiAssistedVisible = isTierVisibleAtDepth('ai_assisted', depth)
|
|
101
|
+
const experimentalVisible = isTierVisibleAtDepth('experimental', depth)
|
|
102
|
+
|
|
103
|
+
console.log(` Tier A (core): ${coreVisible ? 'ā
VISIBLE' : 'ā hidden'}`)
|
|
104
|
+
console.log(` Tier B (ai_assisted): ${aiAssistedVisible ? 'ā
VISIBLE (via AI validation)' : 'ā hidden'}`)
|
|
105
|
+
console.log(` Tier C (experimental): ${experimentalVisible ? 'ā
VISIBLE' : 'ā hidden'}`)
|
|
106
|
+
|
|
107
|
+
// Calculate what would be surfaced
|
|
108
|
+
let surfaced = 0
|
|
109
|
+
let validated = 0
|
|
110
|
+
let hidden = 0
|
|
111
|
+
|
|
112
|
+
if (coreVisible) surfaced += classified.core.length
|
|
113
|
+
else hidden += classified.core.length
|
|
114
|
+
|
|
115
|
+
if (aiAssistedVisible) validated += classified.ai_assisted.length
|
|
116
|
+
else hidden += classified.ai_assisted.length
|
|
117
|
+
|
|
118
|
+
hidden += classified.experimental.length // Always hidden
|
|
119
|
+
|
|
120
|
+
console.log(` ā ${surfaced} surfaced directly, ${validated} to AI validation, ${hidden} hidden`)
|
|
121
|
+
|
|
122
|
+
// Show expected behavior
|
|
123
|
+
switch (depth) {
|
|
124
|
+
case 'cheap':
|
|
125
|
+
console.log(` ā AI validation: SKIPPED`)
|
|
126
|
+
console.log(` ā Layer 3: SKIPPED`)
|
|
127
|
+
console.log(` ā Target time: <5s for typical PRs`)
|
|
128
|
+
break
|
|
129
|
+
case 'validated':
|
|
130
|
+
console.log(` ā AI validation: ENABLED`)
|
|
131
|
+
console.log(` ā Layer 3: SKIPPED`)
|
|
132
|
+
console.log(` ā Target time: <15s with <10 AI calls`)
|
|
133
|
+
break
|
|
134
|
+
case 'deep':
|
|
135
|
+
console.log(` ā AI validation: ENABLED`)
|
|
136
|
+
console.log(` ā Layer 3: ENABLED`)
|
|
137
|
+
console.log(` ā Target time: Thorough analysis`)
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Performance test
|
|
143
|
+
console.log('\n' + '-'.repeat(70))
|
|
144
|
+
console.log('PERFORMANCE VALIDATION')
|
|
145
|
+
console.log('-'.repeat(70))
|
|
146
|
+
|
|
147
|
+
// Test with 10 files
|
|
148
|
+
const files10 = Array.from({ length: 10 }, (_, i) => ({
|
|
149
|
+
...testFile,
|
|
150
|
+
path: `src/api/test-route-${i}.ts`,
|
|
151
|
+
}))
|
|
152
|
+
|
|
153
|
+
console.log('\nā±ļø Testing with 10 files (cheap mode, no AI)...')
|
|
154
|
+
const start10 = Date.now()
|
|
155
|
+
await runLayer1Scan(files10)
|
|
156
|
+
await runLayer2Scan(files10)
|
|
157
|
+
const duration10 = Date.now() - start10
|
|
158
|
+
console.log(` Duration: ${duration10}ms`)
|
|
159
|
+
console.log(` ${duration10 < 5000 ? 'ā
' : 'ā'} Target: <5000ms`)
|
|
160
|
+
|
|
161
|
+
// Test with 50 files
|
|
162
|
+
const files50 = Array.from({ length: 50 }, (_, i) => ({
|
|
163
|
+
...testFile,
|
|
164
|
+
path: `src/api/test-route-${i}.ts`,
|
|
165
|
+
}))
|
|
166
|
+
|
|
167
|
+
console.log('\nā±ļø Testing with 50 files (cheap mode, no AI)...')
|
|
168
|
+
const start50 = Date.now()
|
|
169
|
+
await runLayer1Scan(files50)
|
|
170
|
+
await runLayer2Scan(files50)
|
|
171
|
+
const duration50 = Date.now() - start50
|
|
172
|
+
console.log(` Duration: ${duration50}ms`)
|
|
173
|
+
console.log(` ${duration50 < 10000 ? 'ā
' : 'ā'} Target: <10000ms`)
|
|
174
|
+
console.log(` Rate: ${Math.round(50000 / duration50)} files/sec`)
|
|
175
|
+
|
|
176
|
+
// Summary
|
|
177
|
+
console.log('\n' + '=' .repeat(70))
|
|
178
|
+
console.log('VALIDATION SUMMARY')
|
|
179
|
+
console.log('=' .repeat(70))
|
|
180
|
+
|
|
181
|
+
const allPassed =
|
|
182
|
+
classified.core.length > 0 && // Should have some Tier A findings
|
|
183
|
+
duration10 < 5000 && // 10 files under 5s
|
|
184
|
+
duration50 < 10000 // 50 files under 10s
|
|
185
|
+
|
|
186
|
+
if (allPassed) {
|
|
187
|
+
console.log('\nā
ALL DEPTH PROFILE VALIDATIONS PASSED')
|
|
188
|
+
} else {
|
|
189
|
+
console.log('\nā SOME VALIDATIONS FAILED')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log('\nWorkflow Profile Recommendations:')
|
|
193
|
+
console.log('āāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā')
|
|
194
|
+
console.log('ā Workflow ā Default Depthā Rationale ā')
|
|
195
|
+
console.log('āāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤')
|
|
196
|
+
console.log('ā GitHub PR ā cheap ā Fast feedback, high-signal findingsā')
|
|
197
|
+
console.log('ā VS Code ā validated ā Interactive, balance depth + speed ā')
|
|
198
|
+
console.log('ā CLI (default) ā cheap ā Fast local scans ā')
|
|
199
|
+
console.log('ā CLI --deep ā deep ā Thorough analysis when requested ā')
|
|
200
|
+
console.log('ā Onboarding ā deep ā Full picture on first scan ā')
|
|
201
|
+
console.log('āāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā')
|
|
202
|
+
|
|
203
|
+
console.log('\n')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
runValidation().catch(console.error)
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-World Testing Utility
|
|
3
|
+
* Tests the scanner on actual code patterns and measures performance
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from 'fs'
|
|
7
|
+
import * as path from 'path'
|
|
8
|
+
import { runLayer1Scan } from '../../layer1'
|
|
9
|
+
import { runLayer2Scan } from '../../layer2'
|
|
10
|
+
import { formatTierStats, computeTierStats } from '../../tiers'
|
|
11
|
+
import { formatTerminalOutput } from '../../formatters/cli-terminal'
|
|
12
|
+
import type { ScanFile, Vulnerability, ScanResult } from '../../types'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Test result for a directory scan
|
|
16
|
+
*/
|
|
17
|
+
interface RealWorldTestResult {
|
|
18
|
+
directory: string
|
|
19
|
+
filesScanned: number
|
|
20
|
+
totalFindings: number
|
|
21
|
+
bySeverity: Record<string, number>
|
|
22
|
+
byCategory: Record<string, number>
|
|
23
|
+
scanDuration: number
|
|
24
|
+
filesPerSecond: number
|
|
25
|
+
topFindings: Vulnerability[]
|
|
26
|
+
potentialFalsePositives: Vulnerability[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Scan a local directory and analyze results
|
|
31
|
+
*/
|
|
32
|
+
async function scanDirectory(dirPath: string, maxFiles: number = 100): Promise<RealWorldTestResult> {
|
|
33
|
+
const startTime = Date.now()
|
|
34
|
+
|
|
35
|
+
// Collect files
|
|
36
|
+
const files: ScanFile[] = []
|
|
37
|
+
const extensions = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.java', '.rb', '.php'])
|
|
38
|
+
|
|
39
|
+
function collectFiles(dir: string, depth: number = 0) {
|
|
40
|
+
if (depth > 10 || files.length >= maxFiles) return
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
44
|
+
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
if (files.length >= maxFiles) break
|
|
47
|
+
|
|
48
|
+
const fullPath = path.join(dir, entry.name)
|
|
49
|
+
|
|
50
|
+
// Skip common non-source directories
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
if (['node_modules', '.git', 'dist', 'build', '.next', '__pycache__', 'venv'].includes(entry.name)) {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
collectFiles(fullPath, depth + 1)
|
|
56
|
+
} else if (entry.isFile()) {
|
|
57
|
+
const ext = path.extname(entry.name).toLowerCase()
|
|
58
|
+
if (extensions.has(ext)) {
|
|
59
|
+
try {
|
|
60
|
+
const content = fs.readFileSync(fullPath, 'utf-8')
|
|
61
|
+
if (content.length < 50000) { // Skip very large files
|
|
62
|
+
files.push({
|
|
63
|
+
path: fullPath.replace(dirPath + '/', ''),
|
|
64
|
+
content,
|
|
65
|
+
language: ext.slice(1),
|
|
66
|
+
size: content.length,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
// Skip unreadable files
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
// Skip unreadable directories
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
collectFiles(dirPath)
|
|
81
|
+
|
|
82
|
+
if (files.length === 0) {
|
|
83
|
+
console.log(`No scannable files found in ${dirPath}`)
|
|
84
|
+
return {
|
|
85
|
+
directory: dirPath,
|
|
86
|
+
filesScanned: 0,
|
|
87
|
+
totalFindings: 0,
|
|
88
|
+
bySeverity: {},
|
|
89
|
+
byCategory: {},
|
|
90
|
+
scanDuration: 0,
|
|
91
|
+
filesPerSecond: 0,
|
|
92
|
+
topFindings: [],
|
|
93
|
+
potentialFalsePositives: [],
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log(`Scanning ${files.length} files from ${dirPath}...`)
|
|
98
|
+
|
|
99
|
+
// Run scans
|
|
100
|
+
const layer1Result = await runLayer1Scan(files)
|
|
101
|
+
const layer2Result = await runLayer2Scan(files)
|
|
102
|
+
|
|
103
|
+
const scanDuration = Date.now() - startTime
|
|
104
|
+
const allFindings = [...layer1Result.vulnerabilities, ...layer2Result.vulnerabilities]
|
|
105
|
+
|
|
106
|
+
// Analyze results
|
|
107
|
+
const bySeverity: Record<string, number> = {
|
|
108
|
+
critical: 0,
|
|
109
|
+
high: 0,
|
|
110
|
+
medium: 0,
|
|
111
|
+
low: 0,
|
|
112
|
+
info: 0,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const byCategory: Record<string, number> = {}
|
|
116
|
+
|
|
117
|
+
for (const finding of allFindings) {
|
|
118
|
+
bySeverity[finding.severity] = (bySeverity[finding.severity] || 0) + 1
|
|
119
|
+
byCategory[finding.category] = (byCategory[finding.category] || 0) + 1
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Identify potential false positives (info/low in test files, or common patterns)
|
|
123
|
+
const potentialFalsePositives = allFindings.filter(f => {
|
|
124
|
+
// Test files with any findings
|
|
125
|
+
if (f.filePath.includes('test') || f.filePath.includes('spec')) return true
|
|
126
|
+
// Example/fixture files
|
|
127
|
+
if (f.filePath.includes('example') || f.filePath.includes('fixture')) return true
|
|
128
|
+
// Mock files
|
|
129
|
+
if (f.filePath.includes('mock') || f.filePath.includes('__mocks__')) return true
|
|
130
|
+
return false
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// Sort findings by severity for top findings
|
|
134
|
+
const severityOrder = { critical: 5, high: 4, medium: 3, low: 2, info: 1 }
|
|
135
|
+
const sortedFindings = [...allFindings].sort(
|
|
136
|
+
(a, b) => severityOrder[b.severity] - severityOrder[a.severity]
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
directory: dirPath,
|
|
141
|
+
filesScanned: files.length,
|
|
142
|
+
totalFindings: allFindings.length,
|
|
143
|
+
bySeverity,
|
|
144
|
+
byCategory,
|
|
145
|
+
scanDuration,
|
|
146
|
+
filesPerSecond: Math.round((files.length * 1000) / scanDuration),
|
|
147
|
+
topFindings: sortedFindings.slice(0, 10),
|
|
148
|
+
potentialFalsePositives,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Print test result summary
|
|
154
|
+
*/
|
|
155
|
+
function printResult(result: RealWorldTestResult) {
|
|
156
|
+
console.log('\n' + '='.repeat(70))
|
|
157
|
+
console.log(`REAL-WORLD TEST: ${result.directory}`)
|
|
158
|
+
console.log('='.repeat(70))
|
|
159
|
+
|
|
160
|
+
console.log(`\nš Files scanned: ${result.filesScanned}`)
|
|
161
|
+
console.log(`ā±ļø Scan duration: ${result.scanDuration}ms`)
|
|
162
|
+
console.log(`š Performance: ${result.filesPerSecond} files/sec`)
|
|
163
|
+
|
|
164
|
+
console.log(`\nš Total findings: ${result.totalFindings}`)
|
|
165
|
+
console.log('By severity:')
|
|
166
|
+
for (const [severity, count] of Object.entries(result.bySeverity)) {
|
|
167
|
+
if (count > 0) console.log(` ${severity}: ${count}`)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.log('\nBy category:')
|
|
171
|
+
const sortedCategories = Object.entries(result.byCategory)
|
|
172
|
+
.sort((a, b) => b[1] - a[1])
|
|
173
|
+
.slice(0, 10)
|
|
174
|
+
for (const [category, count] of sortedCategories) {
|
|
175
|
+
console.log(` ${category}: ${count}`)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (result.potentialFalsePositives.length > 0) {
|
|
179
|
+
console.log(`\nā ļø Potential false positives: ${result.potentialFalsePositives.length}`)
|
|
180
|
+
console.log('(Findings in test/example/mock files)')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (result.topFindings.length > 0) {
|
|
184
|
+
console.log('\nš Top findings:')
|
|
185
|
+
for (const finding of result.topFindings.slice(0, 5)) {
|
|
186
|
+
console.log(` [${finding.severity.toUpperCase()}] ${finding.category}: ${finding.title}`)
|
|
187
|
+
console.log(` ${finding.filePath}:${finding.lineNumber}`)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Assessment
|
|
192
|
+
console.log('\n' + '-'.repeat(70))
|
|
193
|
+
console.log('ASSESSMENT')
|
|
194
|
+
console.log('-'.repeat(70))
|
|
195
|
+
|
|
196
|
+
const fpRate = result.totalFindings > 0
|
|
197
|
+
? (result.potentialFalsePositives.length / result.totalFindings * 100).toFixed(1)
|
|
198
|
+
: '0'
|
|
199
|
+
|
|
200
|
+
console.log(`False positive rate (test/mock files): ${fpRate}%`)
|
|
201
|
+
console.log(`Performance target (<5s for 100 files): ${result.scanDuration < 5000 ? 'ā
PASS' : 'ā FAIL'}`)
|
|
202
|
+
|
|
203
|
+
const blockingCount = result.bySeverity.critical + result.bySeverity.high
|
|
204
|
+
if (blockingCount > 0) {
|
|
205
|
+
console.log(`\nā ļø ${blockingCount} blocking issues found - review recommended`)
|
|
206
|
+
} else {
|
|
207
|
+
console.log('\nā
No blocking issues found')
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Run real-world tests
|
|
213
|
+
*/
|
|
214
|
+
async function main() {
|
|
215
|
+
console.log('=' .repeat(70))
|
|
216
|
+
console.log('OCULUM REAL-WORLD TESTING')
|
|
217
|
+
console.log('=' .repeat(70))
|
|
218
|
+
|
|
219
|
+
// Test on the scanner's own codebase
|
|
220
|
+
const scannerPath = path.resolve(__dirname, '../..')
|
|
221
|
+
|
|
222
|
+
console.log('\nš Testing on scanner codebase itself...')
|
|
223
|
+
const result = await scanDirectory(scannerPath, 50)
|
|
224
|
+
printResult(result)
|
|
225
|
+
|
|
226
|
+
// Summary
|
|
227
|
+
console.log('\n' + '='.repeat(70))
|
|
228
|
+
console.log('TESTING COMPLETE')
|
|
229
|
+
console.log('='.repeat(70))
|
|
230
|
+
|
|
231
|
+
console.log('\nTo test on other directories:')
|
|
232
|
+
console.log(' npx tsx src/lib/scanner/__tests__/benchmark/run-real-world-test.ts /path/to/repo')
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Allow testing specific directories via command line
|
|
236
|
+
const targetDir = process.argv[2]
|
|
237
|
+
if (targetDir) {
|
|
238
|
+
scanDirectory(path.resolve(targetDir), 100)
|
|
239
|
+
.then(printResult)
|
|
240
|
+
.catch(console.error)
|
|
241
|
+
} else {
|
|
242
|
+
main().catch(console.error)
|
|
243
|
+
}
|