@oddessentials/odd-ai-reviewers 1.7.4 → 1.8.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.
Files changed (70) hide show
  1. package/dist/agents/ai_semantic_review.d.ts.map +1 -1
  2. package/dist/agents/ai_semantic_review.js +4 -1
  3. package/dist/agents/ai_semantic_review.js.map +1 -1
  4. package/dist/agents/control_flow/safe-source-detector.d.ts +48 -0
  5. package/dist/agents/control_flow/safe-source-detector.d.ts.map +1 -0
  6. package/dist/agents/control_flow/safe-source-detector.js +424 -0
  7. package/dist/agents/control_flow/safe-source-detector.js.map +1 -0
  8. package/dist/agents/control_flow/safe-source-patterns.d.ts +61 -0
  9. package/dist/agents/control_flow/safe-source-patterns.d.ts.map +1 -0
  10. package/dist/agents/control_flow/safe-source-patterns.js +137 -0
  11. package/dist/agents/control_flow/safe-source-patterns.js.map +1 -0
  12. package/dist/agents/control_flow/scope-stack.d.ts +113 -0
  13. package/dist/agents/control_flow/scope-stack.d.ts.map +1 -0
  14. package/dist/agents/control_flow/scope-stack.js +320 -0
  15. package/dist/agents/control_flow/scope-stack.js.map +1 -0
  16. package/dist/agents/control_flow/vulnerability-detector.d.ts +13 -0
  17. package/dist/agents/control_flow/vulnerability-detector.d.ts.map +1 -1
  18. package/dist/agents/control_flow/vulnerability-detector.js +252 -35
  19. package/dist/agents/control_flow/vulnerability-detector.js.map +1 -1
  20. package/dist/agents/opencode.d.ts.map +1 -1
  21. package/dist/agents/opencode.js +4 -1
  22. package/dist/agents/opencode.js.map +1 -1
  23. package/dist/agents/pr_agent.d.ts.map +1 -1
  24. package/dist/agents/pr_agent.js +5 -2
  25. package/dist/agents/pr_agent.js.map +1 -1
  26. package/dist/agents/security.d.ts.map +1 -1
  27. package/dist/agents/security.js +1 -0
  28. package/dist/agents/security.js.map +1 -1
  29. package/dist/agents/types.d.ts +6 -0
  30. package/dist/agents/types.d.ts.map +1 -1
  31. package/dist/benchmark/adapter.d.ts +39 -0
  32. package/dist/benchmark/adapter.d.ts.map +1 -0
  33. package/dist/benchmark/adapter.js +217 -0
  34. package/dist/benchmark/adapter.js.map +1 -0
  35. package/dist/benchmark/scoring.d.ts +100 -0
  36. package/dist/benchmark/scoring.d.ts.map +1 -0
  37. package/dist/benchmark/scoring.js +195 -0
  38. package/dist/benchmark/scoring.js.map +1 -0
  39. package/dist/context-loader.d.ts +80 -0
  40. package/dist/context-loader.d.ts.map +1 -0
  41. package/dist/context-loader.js +202 -0
  42. package/dist/context-loader.js.map +1 -0
  43. package/dist/main.d.ts.map +1 -1
  44. package/dist/main.js +131 -4
  45. package/dist/main.js.map +1 -1
  46. package/dist/phases/index.d.ts +1 -1
  47. package/dist/phases/index.d.ts.map +1 -1
  48. package/dist/phases/index.js +1 -1
  49. package/dist/phases/index.js.map +1 -1
  50. package/dist/phases/report.d.ts +8 -1
  51. package/dist/phases/report.d.ts.map +1 -1
  52. package/dist/phases/report.js +27 -5
  53. package/dist/phases/report.js.map +1 -1
  54. package/dist/report/ado.d.ts +2 -0
  55. package/dist/report/ado.d.ts.map +1 -1
  56. package/dist/report/ado.js +9 -23
  57. package/dist/report/ado.js.map +1 -1
  58. package/dist/report/finding-validator.d.ts +104 -0
  59. package/dist/report/finding-validator.d.ts.map +1 -0
  60. package/dist/report/finding-validator.js +273 -0
  61. package/dist/report/finding-validator.js.map +1 -0
  62. package/dist/report/github.d.ts +2 -0
  63. package/dist/report/github.d.ts.map +1 -1
  64. package/dist/report/github.js +9 -23
  65. package/dist/report/github.js.map +1 -1
  66. package/dist/trust.d.ts +6 -0
  67. package/dist/trust.d.ts.map +1 -1
  68. package/dist/trust.js +2 -0
  69. package/dist/trust.js.map +1 -1
  70. package/package.json +5 -5
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Safe-Source Pattern Definitions
3
+ *
4
+ * Declarative registry of patterns for recognizing provably non-tainted data sources.
5
+ * Safe sources are excluded from taint tracking to prevent false positives.
6
+ *
7
+ * Per contract: safe-source-patterns.md v1.0
8
+ * Per FR-001 through FR-004: Each pattern matches a specific, provable AST shape.
9
+ */
10
+ // =============================================================================
11
+ // Registry Constants
12
+ // =============================================================================
13
+ export const SAFE_SOURCE_REGISTRY_VERSION = '1.0';
14
+ export const EXPECTED_PATTERN_COUNT = 9;
15
+ /**
16
+ * All vulnerability types for patterns that prevent taint universally.
17
+ */
18
+ export const ALL_VULN_TYPES = [
19
+ 'injection',
20
+ 'null_deref',
21
+ 'auth_bypass',
22
+ 'xss',
23
+ 'path_traversal',
24
+ 'prototype_pollution',
25
+ 'ssrf',
26
+ ];
27
+ // =============================================================================
28
+ // Pattern Registry
29
+ // =============================================================================
30
+ export const SAFE_SOURCE_PATTERNS = [
31
+ // Pattern 1: Constant Literal Declarations (FR-001)
32
+ {
33
+ id: 'constant-literal-string',
34
+ name: 'Constant String Literal',
35
+ description: 'Module-scope const with string literal initializer',
36
+ preventsTaintFor: ALL_VULN_TYPES,
37
+ match: {
38
+ type: 'constant_declaration',
39
+ requireModuleScope: true,
40
+ requireLiteralInitializer: true,
41
+ },
42
+ confidence: 'high',
43
+ },
44
+ {
45
+ id: 'constant-literal-number',
46
+ name: 'Constant Number Literal',
47
+ description: 'Module-scope const with numeric literal initializer',
48
+ preventsTaintFor: ALL_VULN_TYPES,
49
+ match: {
50
+ type: 'constant_declaration',
51
+ requireModuleScope: true,
52
+ requireLiteralInitializer: true,
53
+ },
54
+ confidence: 'high',
55
+ },
56
+ {
57
+ id: 'constant-literal-array',
58
+ name: 'Constant Literal Array',
59
+ description: 'Module-scope const with array of literal values',
60
+ preventsTaintFor: ALL_VULN_TYPES,
61
+ match: {
62
+ type: 'constant_declaration',
63
+ requireModuleScope: true,
64
+ requireLiteralInitializer: true,
65
+ },
66
+ confidence: 'high',
67
+ },
68
+ // Pattern 2: Built-in Directory References (FR-002)
69
+ {
70
+ id: 'builtin-dirname',
71
+ name: 'Built-in __dirname',
72
+ description: 'Node.js __dirname built-in reference',
73
+ preventsTaintFor: ['path_traversal'],
74
+ match: {
75
+ type: 'builtin_reference',
76
+ identifiers: ['__dirname'],
77
+ },
78
+ confidence: 'high',
79
+ },
80
+ {
81
+ id: 'builtin-filename',
82
+ name: 'Built-in __filename',
83
+ description: 'Node.js __filename built-in reference',
84
+ preventsTaintFor: ['path_traversal'],
85
+ match: {
86
+ type: 'builtin_reference',
87
+ identifiers: ['__filename'],
88
+ },
89
+ confidence: 'high',
90
+ },
91
+ {
92
+ id: 'builtin-import-meta-dirname',
93
+ name: 'import.meta.dirname',
94
+ description: 'ESM import.meta.dirname reference',
95
+ preventsTaintFor: ['path_traversal'],
96
+ match: {
97
+ type: 'builtin_reference',
98
+ identifiers: ['import.meta.dirname'],
99
+ },
100
+ confidence: 'high',
101
+ },
102
+ {
103
+ id: 'builtin-import-meta-url',
104
+ name: 'import.meta.url',
105
+ description: 'ESM import.meta.url reference',
106
+ preventsTaintFor: ['path_traversal'],
107
+ match: {
108
+ type: 'builtin_reference',
109
+ identifiers: ['import.meta.url'],
110
+ },
111
+ confidence: 'high',
112
+ },
113
+ // Pattern 3: Safe Directory Listing Returns (FR-003)
114
+ {
115
+ id: 'safe-readdir',
116
+ name: 'Safe Directory Listing',
117
+ description: 'fs.readdirSync/readdir with provably safe argument',
118
+ preventsTaintFor: ['path_traversal'],
119
+ match: {
120
+ type: 'safe_function_return',
121
+ callTargets: ['readdirSync', 'readdir'],
122
+ },
123
+ confidence: 'medium',
124
+ },
125
+ // Pattern 4: Constant Array Element Access (FR-004)
126
+ {
127
+ id: 'constant-element-access',
128
+ name: 'Constant Array Element Access',
129
+ description: 'Element access on a module-scope const literal array',
130
+ preventsTaintFor: ['injection', 'xss'],
131
+ match: {
132
+ type: 'constant_element_access',
133
+ },
134
+ confidence: 'high',
135
+ },
136
+ ];
137
+ //# sourceMappingURL=safe-source-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-source-patterns.js","sourceRoot":"","sources":["../../../src/agents/control_flow/safe-source-patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Scope Stack — Lexical scope tracking for declaration-identity resolution.
3
+ *
4
+ * Provides a scope stack that maps variable names to their declaring AST nodes,
5
+ * enabling scope-aware variable resolution without a full TypeChecker.
6
+ *
7
+ * Used by safe-source-detector and vulnerability-detector to replace name-based
8
+ * tracking with declaration-identity tracking.
9
+ */
10
+ import ts from 'typescript';
11
+ /**
12
+ * Produce a deterministic identity string for an AST node.
13
+ * Format: `file:line:col` (1-based line, 0-based column).
14
+ *
15
+ * IMPORTANT: Never embed ts.Node references in serializable data structures.
16
+ * Use this helper to produce a stable key for maps, sets, and stored state.
17
+ */
18
+ export declare function nodeIdentityKey(node: ts.Node, sourceFile: ts.SourceFile): string;
19
+ /**
20
+ * Returns true if `node` introduces a new lexical scope.
21
+ */
22
+ export declare function isScopeNode(node: ts.Node): boolean;
23
+ /**
24
+ * Returns true if `node` introduces a function-level scope (not block-level).
25
+ * Used to determine the correct scope for `var` declarations, which are hoisted
26
+ * to the enclosing function (or source file) rather than the enclosing block.
27
+ */
28
+ export declare function isFunctionScopeNode(node: ts.Node): boolean;
29
+ /**
30
+ * Extract all binding identifiers from a BindingName (handles destructuring).
31
+ *
32
+ * For simple identifiers: `const x = 1` -> ['x']
33
+ * For object destructuring: `const { a, b: c } = obj` -> ['a', 'c']
34
+ * For array destructuring: `const [a, , b] = arr` -> ['a', 'b']
35
+ * For nested: `const { a: [b, c] } = obj` -> ['b', 'c']
36
+ */
37
+ export declare function extractBindingNames(name: ts.BindingName): {
38
+ name: string;
39
+ node: ts.Node;
40
+ }[];
41
+ /**
42
+ * A lexical scope stack for resolving identifier names to declaration nodes.
43
+ *
44
+ * Usage:
45
+ * 1. Walk the AST. On entering a scope-creating node, call `enterScope(node)`.
46
+ * 2. For each variable/const/let declaration, call `addDeclaration(name, declNode)`.
47
+ * 3. To resolve an identifier, call `resolveDeclaration(name)` — returns the
48
+ * innermost declaration node for that name, or undefined if not found.
49
+ * 4. On leaving a scope-creating node, call `leaveScope()`.
50
+ */
51
+ export declare class ScopeStack {
52
+ private stack;
53
+ /** Current nesting depth (0 when no scope is entered). */
54
+ get depth(): number;
55
+ /** Enter a new lexical scope. */
56
+ enterScope(node: ts.Node): void;
57
+ /** Leave the innermost scope. */
58
+ leaveScope(): void;
59
+ /** Register a declaration in the current (innermost) scope. */
60
+ addDeclaration(name: string, node: ts.Node): void;
61
+ /**
62
+ * Register a `var` declaration in the nearest function-level scope.
63
+ * `var` is hoisted to the enclosing function (or source file), not
64
+ * the enclosing block.
65
+ */
66
+ addVarDeclaration(name: string, node: ts.Node): void;
67
+ /**
68
+ * Resolve a name to its declaring node by walking the stack from innermost
69
+ * scope outward. Returns the declaring node, or undefined if the name is
70
+ * not declared in any enclosing scope.
71
+ */
72
+ resolveDeclaration(name: string): ts.Node | undefined;
73
+ /** Check whether a given declaration node is visible in the current scope chain. */
74
+ isInScope(declarationNode: ts.Node): boolean;
75
+ }
76
+ /**
77
+ * Register a variable declaration in the scope stack, handling:
78
+ * - Simple identifiers (`const x`)
79
+ * - Destructuring patterns (`const { a, b } = obj`, `const [a, b] = arr`)
80
+ * - `var` hoisting (registers in the nearest function scope, not block scope)
81
+ * - Catch clause variable binding
82
+ */
83
+ export declare function registerDeclaration(node: ts.VariableDeclaration, scope: ScopeStack, sourceFile?: ts.SourceFile, declarationsByKey?: Map<string, ts.Node>): void;
84
+ /**
85
+ * Register all declaration types for a given node in the scope stack.
86
+ * This is the canonical helper used by all scope-walking code.
87
+ */
88
+ export declare function registerNodeDeclarations(node: ts.Node, scope: ScopeStack, sourceFile?: ts.SourceFile, declarationsByKey?: Map<string, ts.Node>): void;
89
+ /**
90
+ * Build a ScopeStack that is populated with all declarations in `sourceFile`.
91
+ * This performs a full AST walk and registers every variable/const/let/var
92
+ * declaration, function parameter, catch variable, and function declaration name.
93
+ *
94
+ * Returns a Map from each AST node to the ScopeStack state at that point,
95
+ * keyed by node identity string. This is used for point-in-time resolution.
96
+ *
97
+ * For simpler use cases, use `walkWithScope()` instead.
98
+ */
99
+ export declare function buildDeclarationMap(sourceFile: ts.SourceFile): Map<string, ts.Node>;
100
+ /**
101
+ * Walk an AST with scope tracking, invoking a callback for each node.
102
+ * The callback receives the current ScopeStack, which can be used to
103
+ * resolve identifiers at any point during the walk.
104
+ *
105
+ * Declarations are registered automatically for:
106
+ * - Variable declarations (`const x`, `let y`, `var z` with hoisting)
107
+ * - Destructuring patterns (`const { a } = obj`, `const [a] = arr`)
108
+ * - Function declaration names
109
+ * - Function/method/arrow parameters (including destructured)
110
+ * - Catch clause variables
111
+ */
112
+ export declare function walkWithScope(sourceFile: ts.SourceFile, callback: (node: ts.Node, scope: ScopeStack, sourceFile: ts.SourceFile) => void): void;
113
+ //# sourceMappingURL=scope-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-stack.d.ts","sourceRoot":"","sources":["../../../src/agents/control_flow/scope-stack.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAM5B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAGhF;AAmBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAelD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAQ1D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;CAAE,EAAE,CAmB3F;AAMD;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAoB;IAEjC,0DAA0D;IAC1D,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,iCAAiC;IACjC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI;IAQ/B,iCAAiC;IACjC,UAAU,IAAI,IAAI;IAIlB,+DAA+D;IAC/D,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI;IAOjD;;;;OAIG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI;IAgBpD;;;;OAIG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,IAAI,GAAG,SAAS;IAYrD,oFAAoF;IACpF,SAAS,CAAC,eAAe,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO;CAY7C;AAgBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,EAAE,CAAC,mBAAmB,EAC5B,KAAK,EAAE,UAAU,EACjB,UAAU,CAAC,EAAE,EAAE,CAAC,UAAU,EAC1B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GACvC,IAAI,CAeN;AAmCD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,UAAU,EACjB,UAAU,CAAC,EAAE,EAAE,CAAC,UAAU,EAC1B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GACvC,IAAI,CAyBN;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAqBnF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,KAAK,IAAI,GAC9E,IAAI,CAuBN"}
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Scope Stack — Lexical scope tracking for declaration-identity resolution.
3
+ *
4
+ * Provides a scope stack that maps variable names to their declaring AST nodes,
5
+ * enabling scope-aware variable resolution without a full TypeChecker.
6
+ *
7
+ * Used by safe-source-detector and vulnerability-detector to replace name-based
8
+ * tracking with declaration-identity tracking.
9
+ */
10
+ import ts from 'typescript';
11
+ // =============================================================================
12
+ // Identity Key Helper
13
+ // =============================================================================
14
+ /**
15
+ * Produce a deterministic identity string for an AST node.
16
+ * Format: `file:line:col` (1-based line, 0-based column).
17
+ *
18
+ * IMPORTANT: Never embed ts.Node references in serializable data structures.
19
+ * Use this helper to produce a stable key for maps, sets, and stored state.
20
+ */
21
+ export function nodeIdentityKey(node, sourceFile) {
22
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
23
+ return `${sourceFile.fileName}:${line + 1}:${character}`;
24
+ }
25
+ // =============================================================================
26
+ // Scope-Creating Node Detection
27
+ // =============================================================================
28
+ /**
29
+ * Returns true if `node` introduces a new lexical scope.
30
+ */
31
+ export function isScopeNode(node) {
32
+ return (ts.isSourceFile(node) ||
33
+ ts.isBlock(node) ||
34
+ ts.isFunctionDeclaration(node) ||
35
+ ts.isFunctionExpression(node) ||
36
+ ts.isArrowFunction(node) ||
37
+ ts.isMethodDeclaration(node) ||
38
+ ts.isClassDeclaration(node) ||
39
+ ts.isClassExpression(node) ||
40
+ ts.isForStatement(node) ||
41
+ ts.isForOfStatement(node) ||
42
+ ts.isForInStatement(node) ||
43
+ ts.isCatchClause(node));
44
+ }
45
+ /**
46
+ * Returns true if `node` introduces a function-level scope (not block-level).
47
+ * Used to determine the correct scope for `var` declarations, which are hoisted
48
+ * to the enclosing function (or source file) rather than the enclosing block.
49
+ */
50
+ export function isFunctionScopeNode(node) {
51
+ return (ts.isSourceFile(node) ||
52
+ ts.isFunctionDeclaration(node) ||
53
+ ts.isFunctionExpression(node) ||
54
+ ts.isArrowFunction(node) ||
55
+ ts.isMethodDeclaration(node));
56
+ }
57
+ /**
58
+ * Extract all binding identifiers from a BindingName (handles destructuring).
59
+ *
60
+ * For simple identifiers: `const x = 1` -> ['x']
61
+ * For object destructuring: `const { a, b: c } = obj` -> ['a', 'c']
62
+ * For array destructuring: `const [a, , b] = arr` -> ['a', 'b']
63
+ * For nested: `const { a: [b, c] } = obj` -> ['b', 'c']
64
+ */
65
+ export function extractBindingNames(name) {
66
+ const result = [];
67
+ if (ts.isIdentifier(name)) {
68
+ result.push({ name: name.text, node: name });
69
+ }
70
+ else if (ts.isObjectBindingPattern(name)) {
71
+ for (const element of name.elements) {
72
+ result.push(...extractBindingNames(element.name));
73
+ }
74
+ }
75
+ else if (ts.isArrayBindingPattern(name)) {
76
+ for (const element of name.elements) {
77
+ if (ts.isBindingElement(element)) {
78
+ result.push(...extractBindingNames(element.name));
79
+ }
80
+ // OmittedExpression (holes like `[, , x]`) are skipped
81
+ }
82
+ }
83
+ return result;
84
+ }
85
+ // =============================================================================
86
+ // ScopeStack Class
87
+ // =============================================================================
88
+ /**
89
+ * A lexical scope stack for resolving identifier names to declaration nodes.
90
+ *
91
+ * Usage:
92
+ * 1. Walk the AST. On entering a scope-creating node, call `enterScope(node)`.
93
+ * 2. For each variable/const/let declaration, call `addDeclaration(name, declNode)`.
94
+ * 3. To resolve an identifier, call `resolveDeclaration(name)` — returns the
95
+ * innermost declaration node for that name, or undefined if not found.
96
+ * 4. On leaving a scope-creating node, call `leaveScope()`.
97
+ */
98
+ export class ScopeStack {
99
+ stack = [];
100
+ /** Current nesting depth (0 when no scope is entered). */
101
+ get depth() {
102
+ return this.stack.length;
103
+ }
104
+ /** Enter a new lexical scope. */
105
+ enterScope(node) {
106
+ this.stack.push({
107
+ node,
108
+ declarations: new Map(),
109
+ depth: this.stack.length,
110
+ });
111
+ }
112
+ /** Leave the innermost scope. */
113
+ leaveScope() {
114
+ this.stack.pop();
115
+ }
116
+ /** Register a declaration in the current (innermost) scope. */
117
+ addDeclaration(name, node) {
118
+ const top = this.stack[this.stack.length - 1];
119
+ if (top) {
120
+ top.declarations.set(name, node);
121
+ }
122
+ }
123
+ /**
124
+ * Register a `var` declaration in the nearest function-level scope.
125
+ * `var` is hoisted to the enclosing function (or source file), not
126
+ * the enclosing block.
127
+ */
128
+ addVarDeclaration(name, node) {
129
+ for (let i = this.stack.length - 1; i >= 0; i--) {
130
+ const frame = this.stack[i];
131
+ if (!frame)
132
+ continue;
133
+ if (isFunctionScopeNode(frame.node)) {
134
+ frame.declarations.set(name, node);
135
+ return;
136
+ }
137
+ }
138
+ // Fallback: if no function scope found, use the outermost scope
139
+ const outermost = this.stack[0];
140
+ if (outermost) {
141
+ outermost.declarations.set(name, node);
142
+ }
143
+ }
144
+ /**
145
+ * Resolve a name to its declaring node by walking the stack from innermost
146
+ * scope outward. Returns the declaring node, or undefined if the name is
147
+ * not declared in any enclosing scope.
148
+ */
149
+ resolveDeclaration(name) {
150
+ for (let i = this.stack.length - 1; i >= 0; i--) {
151
+ const frame = this.stack[i];
152
+ if (!frame)
153
+ continue;
154
+ const decl = frame.declarations.get(name);
155
+ if (decl !== undefined) {
156
+ return decl;
157
+ }
158
+ }
159
+ return undefined;
160
+ }
161
+ /** Check whether a given declaration node is visible in the current scope chain. */
162
+ isInScope(declarationNode) {
163
+ for (let i = this.stack.length - 1; i >= 0; i--) {
164
+ const frame = this.stack[i];
165
+ if (!frame)
166
+ continue;
167
+ for (const node of frame.declarations.values()) {
168
+ if (node === declarationNode) {
169
+ return true;
170
+ }
171
+ }
172
+ }
173
+ return false;
174
+ }
175
+ }
176
+ // =============================================================================
177
+ // Scope-Walking Helpers
178
+ // =============================================================================
179
+ /**
180
+ * Determine if a variable declaration uses `var` (function-scoped hoisting).
181
+ */
182
+ function isVarDeclaration(node) {
183
+ const declList = node.parent;
184
+ if (!ts.isVariableDeclarationList(declList))
185
+ return false;
186
+ // Neither Const nor Let flag means `var`
187
+ return !(declList.flags & ts.NodeFlags.Const) && !(declList.flags & ts.NodeFlags.Let);
188
+ }
189
+ /**
190
+ * Register a variable declaration in the scope stack, handling:
191
+ * - Simple identifiers (`const x`)
192
+ * - Destructuring patterns (`const { a, b } = obj`, `const [a, b] = arr`)
193
+ * - `var` hoisting (registers in the nearest function scope, not block scope)
194
+ * - Catch clause variable binding
195
+ */
196
+ export function registerDeclaration(node, scope, sourceFile, declarationsByKey) {
197
+ const isVar = isVarDeclaration(node);
198
+ const bindings = extractBindingNames(node.name);
199
+ for (const { name, node: _bindingNode } of bindings) {
200
+ if (isVar) {
201
+ scope.addVarDeclaration(name, node);
202
+ }
203
+ else {
204
+ scope.addDeclaration(name, node);
205
+ }
206
+ if (sourceFile && declarationsByKey) {
207
+ const key = nodeIdentityKey(node, sourceFile);
208
+ declarationsByKey.set(key, node);
209
+ }
210
+ }
211
+ }
212
+ /**
213
+ * Register function parameters (including destructured) in the scope stack.
214
+ */
215
+ function registerParams(node, scope, sourceFile, declarationsByKey) {
216
+ for (const param of node.parameters) {
217
+ const bindings = extractBindingNames(param.name);
218
+ for (const { name } of bindings) {
219
+ scope.addDeclaration(name, param);
220
+ if (sourceFile && declarationsByKey) {
221
+ const key = nodeIdentityKey(param, sourceFile);
222
+ declarationsByKey.set(key, param);
223
+ }
224
+ }
225
+ }
226
+ }
227
+ /**
228
+ * Register a catch clause variable in the scope stack.
229
+ */
230
+ function registerCatchBinding(node, scope) {
231
+ if (node.variableDeclaration) {
232
+ const bindings = extractBindingNames(node.variableDeclaration.name);
233
+ for (const { name } of bindings) {
234
+ scope.addDeclaration(name, node.variableDeclaration);
235
+ }
236
+ }
237
+ }
238
+ /**
239
+ * Register all declaration types for a given node in the scope stack.
240
+ * This is the canonical helper used by all scope-walking code.
241
+ */
242
+ export function registerNodeDeclarations(node, scope, sourceFile, declarationsByKey) {
243
+ if (ts.isVariableDeclaration(node)) {
244
+ registerDeclaration(node, scope, sourceFile, declarationsByKey);
245
+ }
246
+ if (ts.isFunctionDeclaration(node) && node.name) {
247
+ scope.addDeclaration(node.name.text, node);
248
+ if (sourceFile && declarationsByKey) {
249
+ const key = nodeIdentityKey(node, sourceFile);
250
+ declarationsByKey.set(key, node);
251
+ }
252
+ }
253
+ if (ts.isFunctionDeclaration(node) ||
254
+ ts.isFunctionExpression(node) ||
255
+ ts.isArrowFunction(node) ||
256
+ ts.isMethodDeclaration(node)) {
257
+ registerParams(node, scope, sourceFile, declarationsByKey);
258
+ }
259
+ if (ts.isCatchClause(node)) {
260
+ registerCatchBinding(node, scope);
261
+ }
262
+ }
263
+ /**
264
+ * Build a ScopeStack that is populated with all declarations in `sourceFile`.
265
+ * This performs a full AST walk and registers every variable/const/let/var
266
+ * declaration, function parameter, catch variable, and function declaration name.
267
+ *
268
+ * Returns a Map from each AST node to the ScopeStack state at that point,
269
+ * keyed by node identity string. This is used for point-in-time resolution.
270
+ *
271
+ * For simpler use cases, use `walkWithScope()` instead.
272
+ */
273
+ export function buildDeclarationMap(sourceFile) {
274
+ const declarationsByKey = new Map();
275
+ const scope = new ScopeStack();
276
+ const visit = (node) => {
277
+ const isScope = isScopeNode(node);
278
+ if (isScope) {
279
+ scope.enterScope(node);
280
+ }
281
+ registerNodeDeclarations(node, scope, sourceFile, declarationsByKey);
282
+ ts.forEachChild(node, visit);
283
+ if (isScope) {
284
+ scope.leaveScope();
285
+ }
286
+ };
287
+ visit(sourceFile);
288
+ return declarationsByKey;
289
+ }
290
+ /**
291
+ * Walk an AST with scope tracking, invoking a callback for each node.
292
+ * The callback receives the current ScopeStack, which can be used to
293
+ * resolve identifiers at any point during the walk.
294
+ *
295
+ * Declarations are registered automatically for:
296
+ * - Variable declarations (`const x`, `let y`, `var z` with hoisting)
297
+ * - Destructuring patterns (`const { a } = obj`, `const [a] = arr`)
298
+ * - Function declaration names
299
+ * - Function/method/arrow parameters (including destructured)
300
+ * - Catch clause variables
301
+ */
302
+ export function walkWithScope(sourceFile, callback) {
303
+ const scope = new ScopeStack();
304
+ const visit = (node) => {
305
+ const isScope = isScopeNode(node);
306
+ if (isScope) {
307
+ scope.enterScope(node);
308
+ }
309
+ registerNodeDeclarations(node, scope);
310
+ // Invoke user callback
311
+ callback(node, scope, sourceFile);
312
+ // Visit children
313
+ ts.forEachChild(node, visit);
314
+ if (isScope) {
315
+ scope.leaveScope();
316
+ }
317
+ };
318
+ visit(sourceFile);
319
+ }
320
+ //# sourceMappingURL=scope-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-stack.js","sourceRoot":"","sources":["../../../src/agents/control_flow/scope-stack.ts"],"names":[],"mappings":"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"}
@@ -57,16 +57,29 @@ export declare class VulnerabilityDetector {
57
57
  * Find the variable a source is assigned to.
58
58
  */
59
59
  private findAssignedVariable;
60
+ private findAssignedBinding;
61
+ private nodeLocation;
60
62
  /**
61
63
  * Track taint propagation through variable assignments.
64
+ * Uses a scope stack to resolve identifiers to their declaring nodes,
65
+ * keying taint entries by declaration identity instead of raw name.
62
66
  */
63
67
  private trackTaint;
64
68
  /**
65
69
  * Find if an expression uses a tainted variable.
70
+ * Resolves identifiers to their declaring nodes via the scope stack,
71
+ * then matches by declaration identity key rather than raw name.
72
+ * Falls back to name-based matching for taint entries without a declaration key
73
+ * (e.g., initial source entries that weren't resolved during the walk).
66
74
  */
67
75
  private findTaintInExpression;
68
76
  /**
69
77
  * Find the affected variable for a sink.
78
+ *
79
+ * Parses the sink's AST sub-tree to find identifiers, resolves each to its
80
+ * declaration via the scope stack, and matches against tainted entries by
81
+ * declaration identity key. Falls back to name-based matching for taint
82
+ * entries without a declaration key.
70
83
  */
71
84
  private findAffectedVariable;
72
85
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"vulnerability-detector.d.ts","sourceRoot":"","sources":["../../../src/agents/control_flow/vulnerability-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAqB,sBAAsB,EAAkB,MAAM,YAAY,CAAC;AAC5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAoK7D;;;GAGG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAkB;gBAE5B,MAAM,CAAC,EAAE,cAAc;IAMnC;;;;OAIG;IACH,YAAY,CACV,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,uBAAuB,GAC5B,sBAAsB,EAAE;IAoC3B;;OAEG;IACH,OAAO,CAAC,SAAS;IAuBjB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA4ClC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA+B9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA+BlC;;OAEG;IACH,OAAO,CAAC,WAAW;IAsBnB;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAoCpC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAsCnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAuDlB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAiC5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAuB7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAkB5B;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAE1F"}
1
+ {"version":3,"file":"vulnerability-detector.d.ts","sourceRoot":"","sources":["../../../src/agents/control_flow/vulnerability-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAqB,sBAAsB,EAAkB,MAAM,YAAY,CAAC;AAC5F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAqM7D;;;GAGG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAkB;gBAE5B,MAAM,CAAC,EAAE,cAAc;IAMnC;;;;OAIG;IACH,YAAY,CACV,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,uBAAuB,GAC5B,sBAAsB,EAAE;IAiD3B;;OAEG;IACH,OAAO,CAAC,SAAS;IAuBjB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA4ClC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA+B9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA+BlC;;OAEG;IACH,OAAO,CAAC,WAAW;IA+BnB;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAmCpC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAqCnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,mBAAmB;IAsC3B,OAAO,CAAC,YAAY;IASpB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAuJlB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAgC7B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAgG5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAuB7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAkB5B;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAE1F"}