@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,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff Detection Utility
|
|
3
|
+
* Compares current repository tree against previous scan data to detect changed files
|
|
4
|
+
* Used for incremental scanning (Story D)
|
|
5
|
+
*/
|
|
6
|
+
export interface TreeFileInfo {
|
|
7
|
+
path: string;
|
|
8
|
+
sha: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DiffResult {
|
|
11
|
+
/** Files that are new (not in previous scan) */
|
|
12
|
+
added: string[];
|
|
13
|
+
/** Files whose SHA changed (content modified) */
|
|
14
|
+
modified: string[];
|
|
15
|
+
/** Files that were deleted (in previous scan but not in current) */
|
|
16
|
+
deleted: string[];
|
|
17
|
+
/** Files that haven't changed */
|
|
18
|
+
unchanged: string[];
|
|
19
|
+
/** Total count of changed files (added + modified) */
|
|
20
|
+
changedCount: number;
|
|
21
|
+
/** Whether this is a significant change warranting incremental scan */
|
|
22
|
+
shouldUseIncremental: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Detect which files have changed between the current tree and previous scan
|
|
26
|
+
*
|
|
27
|
+
* @param currentTree - Array of files from current GitHub tree (path + sha)
|
|
28
|
+
* @param previousFileShas - Map of {file_path: sha} from previous scan
|
|
29
|
+
* @returns DiffResult with categorized file changes
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectChangedFiles(currentTree: TreeFileInfo[], previousFileShas: Record<string, string> | null | undefined): DiffResult;
|
|
32
|
+
/**
|
|
33
|
+
* Build a file SHA map from a GitHub tree response
|
|
34
|
+
* Filters to only include blob (file) entries
|
|
35
|
+
*
|
|
36
|
+
* @param tree - GitHub tree items with path and sha
|
|
37
|
+
* @returns Map of {file_path: sha}
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildFileShaMap(tree: Array<{
|
|
40
|
+
path: string;
|
|
41
|
+
sha: string;
|
|
42
|
+
type: 'blob' | 'tree';
|
|
43
|
+
}>): Record<string, string>;
|
|
44
|
+
/**
|
|
45
|
+
* Check if two tree SHAs are different
|
|
46
|
+
* Quick check before doing detailed file comparison
|
|
47
|
+
*
|
|
48
|
+
* @param currentTreeSha - SHA of current tree
|
|
49
|
+
* @param previousTreeSha - SHA from previous scan
|
|
50
|
+
* @returns true if trees are different (need detailed comparison)
|
|
51
|
+
*/
|
|
52
|
+
export declare function hasTreeChanged(currentTreeSha: string, previousTreeSha: string | null | undefined): boolean;
|
|
53
|
+
//# sourceMappingURL=diff-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-detector.d.ts","sourceRoot":"","sources":["../../src/utils/diff-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,iDAAiD;IACjD,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,iCAAiC;IACjC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,oBAAoB,EAAE,OAAO,CAAA;CAC9B;AAQD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,YAAY,EAAE,EAC3B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,GAC1D,UAAU,CAsDZ;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC,GAChE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACzC,OAAO,CAGT"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Diff Detection Utility
|
|
4
|
+
* Compares current repository tree against previous scan data to detect changed files
|
|
5
|
+
* Used for incremental scanning (Story D)
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.detectChangedFiles = detectChangedFiles;
|
|
9
|
+
exports.buildFileShaMap = buildFileShaMap;
|
|
10
|
+
exports.hasTreeChanged = hasTreeChanged;
|
|
11
|
+
/**
|
|
12
|
+
* Maximum number of changed files before falling back to full scan
|
|
13
|
+
* Beyond this threshold, incremental mode provides diminishing returns
|
|
14
|
+
*/
|
|
15
|
+
const MAX_CHANGED_FILES_FOR_INCREMENTAL = 50;
|
|
16
|
+
/**
|
|
17
|
+
* Detect which files have changed between the current tree and previous scan
|
|
18
|
+
*
|
|
19
|
+
* @param currentTree - Array of files from current GitHub tree (path + sha)
|
|
20
|
+
* @param previousFileShas - Map of {file_path: sha} from previous scan
|
|
21
|
+
* @returns DiffResult with categorized file changes
|
|
22
|
+
*/
|
|
23
|
+
function detectChangedFiles(currentTree, previousFileShas) {
|
|
24
|
+
// If no previous data, everything is "new"
|
|
25
|
+
if (!previousFileShas || Object.keys(previousFileShas).length === 0) {
|
|
26
|
+
return {
|
|
27
|
+
added: currentTree.map(f => f.path),
|
|
28
|
+
modified: [],
|
|
29
|
+
deleted: [],
|
|
30
|
+
unchanged: [],
|
|
31
|
+
changedCount: currentTree.length,
|
|
32
|
+
shouldUseIncremental: false, // No baseline = full scan
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const added = [];
|
|
36
|
+
const modified = [];
|
|
37
|
+
const unchanged = [];
|
|
38
|
+
const currentPaths = new Set();
|
|
39
|
+
// Compare current files against previous
|
|
40
|
+
for (const file of currentTree) {
|
|
41
|
+
currentPaths.add(file.path);
|
|
42
|
+
const previousSha = previousFileShas[file.path];
|
|
43
|
+
if (!previousSha) {
|
|
44
|
+
// File didn't exist before
|
|
45
|
+
added.push(file.path);
|
|
46
|
+
}
|
|
47
|
+
else if (previousSha !== file.sha) {
|
|
48
|
+
// File content changed (SHA differs)
|
|
49
|
+
modified.push(file.path);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Same SHA = unchanged
|
|
53
|
+
unchanged.push(file.path);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Find deleted files (in previous but not in current)
|
|
57
|
+
const deleted = [];
|
|
58
|
+
for (const path of Object.keys(previousFileShas)) {
|
|
59
|
+
if (!currentPaths.has(path)) {
|
|
60
|
+
deleted.push(path);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const changedCount = added.length + modified.length;
|
|
64
|
+
const shouldUseIncremental = changedCount > 0 && changedCount <= MAX_CHANGED_FILES_FOR_INCREMENTAL;
|
|
65
|
+
return {
|
|
66
|
+
added,
|
|
67
|
+
modified,
|
|
68
|
+
deleted,
|
|
69
|
+
unchanged,
|
|
70
|
+
changedCount,
|
|
71
|
+
shouldUseIncremental,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build a file SHA map from a GitHub tree response
|
|
76
|
+
* Filters to only include blob (file) entries
|
|
77
|
+
*
|
|
78
|
+
* @param tree - GitHub tree items with path and sha
|
|
79
|
+
* @returns Map of {file_path: sha}
|
|
80
|
+
*/
|
|
81
|
+
function buildFileShaMap(tree) {
|
|
82
|
+
const map = {};
|
|
83
|
+
for (const item of tree) {
|
|
84
|
+
// Only include files (blobs), not directories (trees)
|
|
85
|
+
if (item.type === 'blob') {
|
|
86
|
+
map[item.path] = item.sha;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return map;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if two tree SHAs are different
|
|
93
|
+
* Quick check before doing detailed file comparison
|
|
94
|
+
*
|
|
95
|
+
* @param currentTreeSha - SHA of current tree
|
|
96
|
+
* @param previousTreeSha - SHA from previous scan
|
|
97
|
+
* @returns true if trees are different (need detailed comparison)
|
|
98
|
+
*/
|
|
99
|
+
function hasTreeChanged(currentTreeSha, previousTreeSha) {
|
|
100
|
+
if (!previousTreeSha)
|
|
101
|
+
return true;
|
|
102
|
+
return currentTreeSha !== previousTreeSha;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=diff-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-detector.js","sourceRoot":"","sources":["../../src/utils/diff-detector.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAmCH,gDAyDC;AASD,0CAaC;AAUD,wCAMC;AA5GD;;;GAGG;AACH,MAAM,iCAAiC,GAAG,EAAE,CAAA;AAE5C;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAChC,WAA2B,EAC3B,gBAA2D;IAE3D,2CAA2C;IAC3C,IAAI,CAAC,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,OAAO;YACL,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACnC,QAAQ,EAAE,EAAE;YACZ,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,WAAW,CAAC,MAAM;YAChC,oBAAoB,EAAE,KAAK,EAAE,0BAA0B;SACxD,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IAEtC,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE/C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,2BAA2B;YAC3B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvB,CAAC;aAAM,IAAI,WAAW,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,qCAAqC;YACrC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1B,CAAC;aAAM,CAAC;YACN,uBAAuB;YACvB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;IACnD,MAAM,oBAAoB,GAAG,YAAY,GAAG,CAAC,IAAI,YAAY,IAAI,iCAAiC,CAAA;IAElG,OAAO;QACL,KAAK;QACL,QAAQ;QACR,OAAO;QACP,SAAS;QACT,YAAY;QACZ,oBAAoB;KACrB,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,eAAe,CAC7B,IAAiE;IAEjE,MAAM,GAAG,GAA2B,EAAE,CAAA;IAEtC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,sDAAsD;QACtD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,cAAc,CAC5B,cAAsB,EACtB,eAA0C;IAE1C,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAA;IACjC,OAAO,cAAc,KAAK,eAAe,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Diff Parser
|
|
3
|
+
* Parses unified diff format to extract changed line ranges
|
|
4
|
+
* Used for incremental scanning to only flag findings on changed lines
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* A hunk represents a contiguous block of changes
|
|
8
|
+
*/
|
|
9
|
+
export interface DiffHunk {
|
|
10
|
+
/** Starting line in the old file */
|
|
11
|
+
oldStart: number;
|
|
12
|
+
/** Number of lines in old file */
|
|
13
|
+
oldLines: number;
|
|
14
|
+
/** Starting line in the new file */
|
|
15
|
+
newStart: number;
|
|
16
|
+
/** Number of lines in new file */
|
|
17
|
+
newLines: number;
|
|
18
|
+
/** Lines that were added (line numbers in new file) */
|
|
19
|
+
addedLines: number[];
|
|
20
|
+
/** Lines that were removed (line numbers in old file) */
|
|
21
|
+
removedLines: number[];
|
|
22
|
+
/** Lines that were modified (context around changes in new file) */
|
|
23
|
+
contextLines: number[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parsed file diff
|
|
27
|
+
*/
|
|
28
|
+
export interface FileDiff {
|
|
29
|
+
/** File path (after rename if applicable) */
|
|
30
|
+
path: string;
|
|
31
|
+
/** Old file path (if renamed) */
|
|
32
|
+
oldPath?: string;
|
|
33
|
+
/** Whether the file was added */
|
|
34
|
+
isNew: boolean;
|
|
35
|
+
/** Whether the file was deleted */
|
|
36
|
+
isDeleted: boolean;
|
|
37
|
+
/** Whether the file was renamed */
|
|
38
|
+
isRenamed: boolean;
|
|
39
|
+
/** Hunks containing the actual changes */
|
|
40
|
+
hunks: DiffHunk[];
|
|
41
|
+
/** All changed line numbers in the new file */
|
|
42
|
+
changedLines: Set<number>;
|
|
43
|
+
/** All lines near changes (within context window) */
|
|
44
|
+
affectedLines: Set<number>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parse a unified diff output
|
|
48
|
+
*
|
|
49
|
+
* @param diffOutput - The raw git diff output
|
|
50
|
+
* @param contextWindow - Lines around changes to consider "affected" (default: 5)
|
|
51
|
+
* @returns Map of file path to FileDiff
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseDiff(diffOutput: string, contextWindow?: number): Map<string, FileDiff>;
|
|
54
|
+
/**
|
|
55
|
+
* Parse a simple list of changed file paths
|
|
56
|
+
* Used when full diff isn't available (e.g., GitHub API file list)
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseChangedFileList(files: string[]): Map<string, FileDiff>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if a finding is on a changed line
|
|
61
|
+
*/
|
|
62
|
+
export declare function isOnChangedLine(filePath: string, lineNumber: number, diffs: Map<string, FileDiff>): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Check if a finding is near a changed line (within context window)
|
|
65
|
+
*/
|
|
66
|
+
export declare function isNearChangedLine(filePath: string, lineNumber: number, diffs: Map<string, FileDiff>): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Get all changed file paths from diffs
|
|
69
|
+
*/
|
|
70
|
+
export declare function getChangedFilePaths(diffs: Map<string, FileDiff>): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Filter vulnerabilities to only those on/near changed lines
|
|
73
|
+
*/
|
|
74
|
+
export declare function filterToChangedLines<T extends {
|
|
75
|
+
filePath: string;
|
|
76
|
+
lineNumber: number;
|
|
77
|
+
}>(findings: T[], diffs: Map<string, FileDiff>, options?: {
|
|
78
|
+
strictMode?: boolean;
|
|
79
|
+
}): T[];
|
|
80
|
+
//# sourceMappingURL=diff-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-parser.d.ts","sourceRoot":"","sources":["../../src/utils/diff-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,yDAAyD;IACzD,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,oEAAoE;IACpE,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAA;IACd,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAA;IAClB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAA;IAClB,0CAA0C;IAC1C,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,+CAA+C;IAC/C,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzB,qDAAqD;IACrD,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,GAAE,MAAU,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAkB9F;AA6GD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAiB3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC3B,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAC3B,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CAK1E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EACrF,QAAQ,EAAE,CAAC,EAAE,EACb,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,CAAC,EAAE,CAeL"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git Diff Parser
|
|
4
|
+
* Parses unified diff format to extract changed line ranges
|
|
5
|
+
* Used for incremental scanning to only flag findings on changed lines
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.parseDiff = parseDiff;
|
|
9
|
+
exports.parseChangedFileList = parseChangedFileList;
|
|
10
|
+
exports.isOnChangedLine = isOnChangedLine;
|
|
11
|
+
exports.isNearChangedLine = isNearChangedLine;
|
|
12
|
+
exports.getChangedFilePaths = getChangedFilePaths;
|
|
13
|
+
exports.filterToChangedLines = filterToChangedLines;
|
|
14
|
+
/**
|
|
15
|
+
* Parse a unified diff output
|
|
16
|
+
*
|
|
17
|
+
* @param diffOutput - The raw git diff output
|
|
18
|
+
* @param contextWindow - Lines around changes to consider "affected" (default: 5)
|
|
19
|
+
* @returns Map of file path to FileDiff
|
|
20
|
+
*/
|
|
21
|
+
function parseDiff(diffOutput, contextWindow = 5) {
|
|
22
|
+
const files = new Map();
|
|
23
|
+
if (!diffOutput || diffOutput.trim() === '') {
|
|
24
|
+
return files;
|
|
25
|
+
}
|
|
26
|
+
// Split into file sections (each starts with "diff --git")
|
|
27
|
+
const fileSections = diffOutput.split(/^diff --git /gm).filter(s => s.trim());
|
|
28
|
+
for (const section of fileSections) {
|
|
29
|
+
const fileDiff = parseFileSection('diff --git ' + section, contextWindow);
|
|
30
|
+
if (fileDiff) {
|
|
31
|
+
files.set(fileDiff.path, fileDiff);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return files;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a single file's diff section
|
|
38
|
+
*/
|
|
39
|
+
function parseFileSection(section, contextWindow) {
|
|
40
|
+
const lines = section.split('\n');
|
|
41
|
+
// Extract file paths from header
|
|
42
|
+
// Format: diff --git a/path/to/file b/path/to/file
|
|
43
|
+
const headerMatch = lines[0].match(/diff --git a\/(.+) b\/(.+)/);
|
|
44
|
+
if (!headerMatch)
|
|
45
|
+
return null;
|
|
46
|
+
const oldPath = headerMatch[1];
|
|
47
|
+
const newPath = headerMatch[2];
|
|
48
|
+
// Detect file status
|
|
49
|
+
let isNew = false;
|
|
50
|
+
let isDeleted = false;
|
|
51
|
+
let isRenamed = oldPath !== newPath;
|
|
52
|
+
for (const line of lines.slice(0, 10)) {
|
|
53
|
+
if (line.startsWith('new file mode'))
|
|
54
|
+
isNew = true;
|
|
55
|
+
if (line.startsWith('deleted file mode'))
|
|
56
|
+
isDeleted = true;
|
|
57
|
+
if (line.startsWith('rename from'))
|
|
58
|
+
isRenamed = true;
|
|
59
|
+
}
|
|
60
|
+
// Parse hunks
|
|
61
|
+
const hunks = [];
|
|
62
|
+
const changedLines = new Set();
|
|
63
|
+
const affectedLines = new Set();
|
|
64
|
+
// Find hunk headers: @@ -oldStart,oldLines +newStart,newLines @@
|
|
65
|
+
const hunkRegex = /@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/g;
|
|
66
|
+
let match;
|
|
67
|
+
const sectionContent = section;
|
|
68
|
+
while ((match = hunkRegex.exec(sectionContent)) !== null) {
|
|
69
|
+
const oldStart = parseInt(match[1], 10);
|
|
70
|
+
const oldLines = parseInt(match[2] || '1', 10);
|
|
71
|
+
const newStart = parseInt(match[3], 10);
|
|
72
|
+
const newLines = parseInt(match[4] || '1', 10);
|
|
73
|
+
// Find the content of this hunk (until next @@ or end)
|
|
74
|
+
const hunkStartIndex = match.index + match[0].length;
|
|
75
|
+
const nextHunkMatch = /@@ -\d+/.exec(sectionContent.slice(hunkStartIndex + 1));
|
|
76
|
+
const hunkEndIndex = nextHunkMatch
|
|
77
|
+
? hunkStartIndex + 1 + nextHunkMatch.index
|
|
78
|
+
: sectionContent.length;
|
|
79
|
+
const hunkContent = sectionContent.slice(hunkStartIndex, hunkEndIndex);
|
|
80
|
+
const hunkLines = hunkContent.split('\n');
|
|
81
|
+
const addedLines = [];
|
|
82
|
+
const removedLines = [];
|
|
83
|
+
const contextLines = [];
|
|
84
|
+
let newLineNum = newStart;
|
|
85
|
+
let oldLineNum = oldStart;
|
|
86
|
+
for (const line of hunkLines) {
|
|
87
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
88
|
+
// Added line
|
|
89
|
+
addedLines.push(newLineNum);
|
|
90
|
+
changedLines.add(newLineNum);
|
|
91
|
+
newLineNum++;
|
|
92
|
+
}
|
|
93
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
94
|
+
// Removed line
|
|
95
|
+
removedLines.push(oldLineNum);
|
|
96
|
+
oldLineNum++;
|
|
97
|
+
}
|
|
98
|
+
else if (line.startsWith(' ') || line === '') {
|
|
99
|
+
// Context line
|
|
100
|
+
contextLines.push(newLineNum);
|
|
101
|
+
newLineNum++;
|
|
102
|
+
oldLineNum++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
hunks.push({
|
|
106
|
+
oldStart,
|
|
107
|
+
oldLines,
|
|
108
|
+
newStart,
|
|
109
|
+
newLines,
|
|
110
|
+
addedLines,
|
|
111
|
+
removedLines,
|
|
112
|
+
contextLines,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Calculate affected lines (changed lines + context window)
|
|
116
|
+
for (const line of changedLines) {
|
|
117
|
+
for (let i = Math.max(1, line - contextWindow); i <= line + contextWindow; i++) {
|
|
118
|
+
affectedLines.add(i);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
path: newPath,
|
|
123
|
+
oldPath: isRenamed ? oldPath : undefined,
|
|
124
|
+
isNew,
|
|
125
|
+
isDeleted,
|
|
126
|
+
isRenamed,
|
|
127
|
+
hunks,
|
|
128
|
+
changedLines,
|
|
129
|
+
affectedLines,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse a simple list of changed file paths
|
|
134
|
+
* Used when full diff isn't available (e.g., GitHub API file list)
|
|
135
|
+
*/
|
|
136
|
+
function parseChangedFileList(files) {
|
|
137
|
+
const result = new Map();
|
|
138
|
+
for (const path of files) {
|
|
139
|
+
result.set(path, {
|
|
140
|
+
path,
|
|
141
|
+
isNew: false,
|
|
142
|
+
isDeleted: false,
|
|
143
|
+
isRenamed: false,
|
|
144
|
+
hunks: [],
|
|
145
|
+
// Without diff content, consider all lines as changed
|
|
146
|
+
changedLines: new Set(),
|
|
147
|
+
affectedLines: new Set(),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if a finding is on a changed line
|
|
154
|
+
*/
|
|
155
|
+
function isOnChangedLine(filePath, lineNumber, diffs) {
|
|
156
|
+
const fileDiff = diffs.get(filePath);
|
|
157
|
+
if (!fileDiff)
|
|
158
|
+
return false;
|
|
159
|
+
// If no specific changed lines (file list only), consider all findings relevant
|
|
160
|
+
if (fileDiff.changedLines.size === 0)
|
|
161
|
+
return true;
|
|
162
|
+
return fileDiff.changedLines.has(lineNumber);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Check if a finding is near a changed line (within context window)
|
|
166
|
+
*/
|
|
167
|
+
function isNearChangedLine(filePath, lineNumber, diffs) {
|
|
168
|
+
const fileDiff = diffs.get(filePath);
|
|
169
|
+
if (!fileDiff)
|
|
170
|
+
return false;
|
|
171
|
+
// If no specific affected lines, consider all findings relevant
|
|
172
|
+
if (fileDiff.affectedLines.size === 0)
|
|
173
|
+
return true;
|
|
174
|
+
return fileDiff.affectedLines.has(lineNumber);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get all changed file paths from diffs
|
|
178
|
+
*/
|
|
179
|
+
function getChangedFilePaths(diffs) {
|
|
180
|
+
return Array.from(diffs.keys()).filter(path => {
|
|
181
|
+
const diff = diffs.get(path);
|
|
182
|
+
return diff && !diff.isDeleted;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Filter vulnerabilities to only those on/near changed lines
|
|
187
|
+
*/
|
|
188
|
+
function filterToChangedLines(findings, diffs, options = {}) {
|
|
189
|
+
const { strictMode = false } = options;
|
|
190
|
+
return findings.filter(finding => {
|
|
191
|
+
// If file not in diff, it wasn't changed - exclude
|
|
192
|
+
if (!diffs.has(finding.filePath))
|
|
193
|
+
return false;
|
|
194
|
+
// In strict mode, only include findings on exactly changed lines
|
|
195
|
+
if (strictMode) {
|
|
196
|
+
return isOnChangedLine(finding.filePath, finding.lineNumber, diffs);
|
|
197
|
+
}
|
|
198
|
+
// In normal mode, include findings near changed lines
|
|
199
|
+
return isNearChangedLine(finding.filePath, finding.lineNumber, diffs);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=diff-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-parser.js","sourceRoot":"","sources":["../../src/utils/diff-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imported Auth Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects auth middleware/helpers imported from other files to avoid
|
|
5
|
+
* false positives on routes that are actually protected via imports.
|
|
6
|
+
*
|
|
7
|
+
* Example: A route file that does `import { authMiddleware } from '@/lib/auth'`
|
|
8
|
+
* and wraps handlers with it should not be flagged as "missing auth".
|
|
9
|
+
*/
|
|
10
|
+
import type { ScanFile } from '../types';
|
|
11
|
+
export interface ImportedAuthInfo {
|
|
12
|
+
importPath: string;
|
|
13
|
+
importedNames: string[];
|
|
14
|
+
isAuthRelated: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface FileAuthImports {
|
|
17
|
+
filePath: string;
|
|
18
|
+
imports: ImportedAuthInfo[];
|
|
19
|
+
usesImportedAuth: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Extract all imports from a file's content
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractImports(content: string): ImportedAuthInfo[];
|
|
25
|
+
/**
|
|
26
|
+
* Check if imported auth is actually used to protect routes/handlers
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectImportedAuthUsage(content: string, authImports: ImportedAuthInfo[]): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Build a registry of files and their auth imports
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildFileAuthImports(files: ScanFile[]): Map<string, FileAuthImports>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a specific file uses imported auth protection
|
|
35
|
+
*/
|
|
36
|
+
export declare function fileUsesImportedAuth(filePath: string, registry: Map<string, FileAuthImports>): boolean;
|
|
37
|
+
//# sourceMappingURL=imported-auth-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imported-auth-detector.d.ts","sourceRoot":"","sources":["../../src/utils/imported-auth-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAMxC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAkFD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA8ElE;AA+BD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,gBAAgB,EAAE,GAC9B,OAAO,CAgDT;AAaD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAmBpF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GACrC,OAAO,CAET"}
|