@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.
- package/dist/agents/ai_semantic_review.d.ts.map +1 -1
- package/dist/agents/ai_semantic_review.js +4 -1
- package/dist/agents/ai_semantic_review.js.map +1 -1
- package/dist/agents/control_flow/safe-source-detector.d.ts +48 -0
- package/dist/agents/control_flow/safe-source-detector.d.ts.map +1 -0
- package/dist/agents/control_flow/safe-source-detector.js +424 -0
- package/dist/agents/control_flow/safe-source-detector.js.map +1 -0
- package/dist/agents/control_flow/safe-source-patterns.d.ts +61 -0
- package/dist/agents/control_flow/safe-source-patterns.d.ts.map +1 -0
- package/dist/agents/control_flow/safe-source-patterns.js +137 -0
- package/dist/agents/control_flow/safe-source-patterns.js.map +1 -0
- package/dist/agents/control_flow/scope-stack.d.ts +113 -0
- package/dist/agents/control_flow/scope-stack.d.ts.map +1 -0
- package/dist/agents/control_flow/scope-stack.js +320 -0
- package/dist/agents/control_flow/scope-stack.js.map +1 -0
- package/dist/agents/control_flow/vulnerability-detector.d.ts +13 -0
- package/dist/agents/control_flow/vulnerability-detector.d.ts.map +1 -1
- package/dist/agents/control_flow/vulnerability-detector.js +252 -35
- package/dist/agents/control_flow/vulnerability-detector.js.map +1 -1
- package/dist/agents/opencode.d.ts.map +1 -1
- package/dist/agents/opencode.js +4 -1
- package/dist/agents/opencode.js.map +1 -1
- package/dist/agents/pr_agent.d.ts.map +1 -1
- package/dist/agents/pr_agent.js +5 -2
- package/dist/agents/pr_agent.js.map +1 -1
- package/dist/agents/security.d.ts.map +1 -1
- package/dist/agents/security.js +1 -0
- package/dist/agents/security.js.map +1 -1
- package/dist/agents/types.d.ts +6 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/benchmark/adapter.d.ts +39 -0
- package/dist/benchmark/adapter.d.ts.map +1 -0
- package/dist/benchmark/adapter.js +217 -0
- package/dist/benchmark/adapter.js.map +1 -0
- package/dist/benchmark/scoring.d.ts +100 -0
- package/dist/benchmark/scoring.d.ts.map +1 -0
- package/dist/benchmark/scoring.js +195 -0
- package/dist/benchmark/scoring.js.map +1 -0
- package/dist/context-loader.d.ts +80 -0
- package/dist/context-loader.d.ts.map +1 -0
- package/dist/context-loader.js +202 -0
- package/dist/context-loader.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +131 -4
- package/dist/main.js.map +1 -1
- package/dist/phases/index.d.ts +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +1 -1
- package/dist/phases/index.js.map +1 -1
- package/dist/phases/report.d.ts +8 -1
- package/dist/phases/report.d.ts.map +1 -1
- package/dist/phases/report.js +27 -5
- package/dist/phases/report.js.map +1 -1
- package/dist/report/ado.d.ts +2 -0
- package/dist/report/ado.d.ts.map +1 -1
- package/dist/report/ado.js +9 -23
- package/dist/report/ado.js.map +1 -1
- package/dist/report/finding-validator.d.ts +104 -0
- package/dist/report/finding-validator.d.ts.map +1 -0
- package/dist/report/finding-validator.js +273 -0
- package/dist/report/finding-validator.js.map +1 -0
- package/dist/report/github.d.ts +2 -0
- package/dist/report/github.d.ts.map +1 -1
- package/dist/report/github.js +9 -23
- package/dist/report/github.js.map +1 -1
- package/dist/trust.d.ts +6 -0
- package/dist/trust.d.ts.map +1 -1
- package/dist/trust.js +2 -0
- package/dist/trust.js.map +1 -1
- 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;
|
|
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"}
|