@kernlang/review 3.1.5 → 3.1.7
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/LICENSE +17 -0
- package/dist/cache.d.ts +1 -1
- package/dist/cache.js +5 -3
- package/dist/cache.js.map +1 -1
- package/dist/call-graph.d.ts +63 -0
- package/dist/call-graph.js +380 -0
- package/dist/call-graph.js.map +1 -0
- package/dist/concept-rules/boundary-mutation.d.ts +1 -1
- package/dist/concept-rules/boundary-mutation.js.map +1 -1
- package/dist/concept-rules/ignored-error.d.ts +1 -1
- package/dist/concept-rules/ignored-error.js.map +1 -1
- package/dist/concept-rules/illegal-dependency.d.ts +1 -1
- package/dist/concept-rules/illegal-dependency.js.map +1 -1
- package/dist/concept-rules/index.js +1 -6
- package/dist/concept-rules/index.js.map +1 -1
- package/dist/concept-rules/unguarded-effect.d.ts +1 -1
- package/dist/concept-rules/unguarded-effect.js.map +1 -1
- package/dist/concept-rules/unrecovered-effect.d.ts +1 -1
- package/dist/concept-rules/unrecovered-effect.js +2 -1
- package/dist/concept-rules/unrecovered-effect.js.map +1 -1
- package/dist/confidence.js +12 -8
- package/dist/confidence.js.map +1 -1
- package/dist/differ.js +3 -7
- package/dist/differ.js.map +1 -1
- package/dist/external-tools.js +5 -6
- package/dist/external-tools.js.map +1 -1
- package/dist/file-context.d.ts +21 -0
- package/dist/file-context.js +234 -0
- package/dist/file-context.js.map +1 -0
- package/dist/file-role.js +14 -7
- package/dist/file-role.js.map +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/graph.js +24 -16
- package/dist/graph.js.map +1 -1
- package/dist/index.d.ts +44 -35
- package/dist/index.js +221 -68
- package/dist/index.js.map +1 -1
- package/dist/inferrer.d.ts +8 -2
- package/dist/inferrer.js +80 -47
- package/dist/inferrer.js.map +1 -1
- package/dist/kern-lint.d.ts +3 -4
- package/dist/kern-lint.js +7 -5
- package/dist/kern-lint.js.map +1 -1
- package/dist/llm-bridge.d.ts +23 -7
- package/dist/llm-bridge.js +267 -31
- package/dist/llm-bridge.js.map +1 -1
- package/dist/llm-review.d.ts +16 -2
- package/dist/llm-review.js +240 -35
- package/dist/llm-review.js.map +1 -1
- package/dist/mappers/ts-concepts.d.ts +1 -1
- package/dist/mappers/ts-concepts.js +303 -32
- package/dist/mappers/ts-concepts.js.map +1 -1
- package/dist/norm-miner.d.ts +31 -0
- package/dist/norm-miner.js +119 -0
- package/dist/norm-miner.js.map +1 -0
- package/dist/obligations.d.ts +63 -0
- package/dist/obligations.js +158 -0
- package/dist/obligations.js.map +1 -0
- package/dist/quality-rules.d.ts +3 -3
- package/dist/quality-rules.js +4 -2
- package/dist/quality-rules.js.map +1 -1
- package/dist/reporter.d.ts +7 -2
- package/dist/reporter.js +82 -51
- package/dist/reporter.js.map +1 -1
- package/dist/rule-eval.d.ts +1 -2
- package/dist/rule-eval.js +5 -9
- package/dist/rule-eval.js.map +1 -1
- package/dist/rule-loader.js +16 -14
- package/dist/rule-loader.js.map +1 -1
- package/dist/rules/base.js +153 -69
- package/dist/rules/base.js.map +1 -1
- package/dist/rules/cli.d.ts +7 -0
- package/dist/rules/cli.js +99 -0
- package/dist/rules/cli.js.map +1 -0
- package/dist/rules/confidence.d.ts +1 -1
- package/dist/rules/confidence.js +5 -5
- package/dist/rules/confidence.js.map +1 -1
- package/dist/rules/dead-code.d.ts +10 -0
- package/dist/rules/dead-code.js +75 -0
- package/dist/rules/dead-code.js.map +1 -0
- package/dist/rules/dead-logic.js +35 -31
- package/dist/rules/dead-logic.js.map +1 -1
- package/dist/rules/express.d.ts +2 -1
- package/dist/rules/express.js +380 -126
- package/dist/rules/express.js.map +1 -1
- package/dist/rules/fastapi.d.ts +10 -0
- package/dist/rules/fastapi.js +183 -0
- package/dist/rules/fastapi.js.map +1 -0
- package/dist/rules/ground-layer.js +3 -3
- package/dist/rules/ground-layer.js.map +1 -1
- package/dist/rules/index.d.ts +5 -1
- package/dist/rules/index.js +602 -84
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/ink.d.ts +8 -0
- package/dist/rules/ink.js +88 -0
- package/dist/rules/ink.js.map +1 -0
- package/dist/rules/kern-source.js +202 -63
- package/dist/rules/kern-source.js.map +1 -1
- package/dist/rules/nextjs.js +88 -33
- package/dist/rules/nextjs.js.map +1 -1
- package/dist/rules/null-safety.js +52 -26
- package/dist/rules/null-safety.js.map +1 -1
- package/dist/rules/nuxt.js +24 -29
- package/dist/rules/nuxt.js.map +1 -1
- package/dist/rules/react.js +355 -69
- package/dist/rules/react.js.map +1 -1
- package/dist/rules/security-v2.js +71 -57
- package/dist/rules/security-v2.js.map +1 -1
- package/dist/rules/security-v3.js.map +1 -1
- package/dist/rules/security-v4.js +54 -27
- package/dist/rules/security-v4.js.map +1 -1
- package/dist/rules/security.js +35 -5
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/terminal.d.ts +8 -0
- package/dist/rules/terminal.js +139 -0
- package/dist/rules/terminal.js.map +1 -0
- package/dist/rules/vue.js +162 -107
- package/dist/rules/vue.js.map +1 -1
- package/dist/semantic-diff.d.ts +52 -0
- package/dist/semantic-diff.js +342 -0
- package/dist/semantic-diff.js.map +1 -0
- package/dist/spec-checker.js +11 -10
- package/dist/spec-checker.js.map +1 -1
- package/dist/suppression/apply-suppression.d.ts +2 -3
- package/dist/suppression/apply-suppression.js +3 -3
- package/dist/suppression/apply-suppression.js.map +1 -1
- package/dist/suppression/index.d.ts +2 -2
- package/dist/suppression/index.js +1 -1
- package/dist/suppression/index.js.map +1 -1
- package/dist/suppression/parse-directives.d.ts +1 -1
- package/dist/suppression/parse-directives.js +9 -4
- package/dist/suppression/parse-directives.js.map +1 -1
- package/dist/taint-ast.d.ts +20 -0
- package/dist/taint-ast.js +427 -0
- package/dist/taint-ast.js.map +1 -0
- package/dist/taint-crossfile.d.ts +28 -0
- package/dist/taint-crossfile.js +174 -0
- package/dist/taint-crossfile.js.map +1 -0
- package/dist/taint-findings.d.ts +17 -0
- package/dist/taint-findings.js +131 -0
- package/dist/taint-findings.js.map +1 -0
- package/dist/taint-regex.d.ts +61 -0
- package/dist/taint-regex.js +379 -0
- package/dist/taint-regex.js.map +1 -0
- package/dist/taint-types.d.ts +128 -0
- package/dist/taint-types.js +174 -0
- package/dist/taint-types.js.map +1 -0
- package/dist/taint.d.ts +13 -107
- package/dist/taint.js +16 -1067
- package/dist/taint.js.map +1 -1
- package/dist/template-detector.d.ts +2 -2
- package/dist/template-detector.js +11 -16
- package/dist/template-detector.js.map +1 -1
- package/dist/types.d.ts +35 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-directives.js","sourceRoot":"","sources":["../../src/suppression/parse-directives.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"parse-directives.js","sourceRoot":"","sources":["../../src/suppression/parse-directives.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — AST-based engine using ts-morph.
|
|
3
|
+
*
|
|
4
|
+
* Handles destructuring, method chains, computed property access,
|
|
5
|
+
* and interprocedural taint through intra-file call graph.
|
|
6
|
+
*/
|
|
7
|
+
import { type SourceFile } from 'ts-morph';
|
|
8
|
+
import type { InternalSinkFunction, TaintResult } from './taint-types.js';
|
|
9
|
+
import type { InferResult } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build a map of internal functions that contain sinks.
|
|
12
|
+
* For each function, determine which parameters flow to sinks.
|
|
13
|
+
* This enables interprocedural taint: processInput(req.body) → exec() is now visible.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildInternalSinkMap(sourceFile: SourceFile): Map<string, InternalSinkFunction>;
|
|
16
|
+
/**
|
|
17
|
+
* AST-based taint analysis — walks real ts-morph AST nodes instead of regex on strings.
|
|
18
|
+
* Handles destructuring, method chains, computed property access.
|
|
19
|
+
*/
|
|
20
|
+
export declare function analyzeTaintAST(_inferred: InferResult[], filePath: string, sourceFile: SourceFile): TaintResult[];
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — AST-based engine using ts-morph.
|
|
3
|
+
*
|
|
4
|
+
* Handles destructuring, method chains, computed property access,
|
|
5
|
+
* and interprocedural taint through intra-file call graph.
|
|
6
|
+
*/
|
|
7
|
+
import { SyntaxKind, } from 'ts-morph';
|
|
8
|
+
import { HTTP_PARAM_NAMES, HTTP_PARAM_TYPES, isSanitizerSufficient, SANITIZER_PATTERN_NAMES, SINK_NAMES, } from './taint-types.js';
|
|
9
|
+
// ── Intra-File Sink Map ─────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Build a map of internal functions that contain sinks.
|
|
12
|
+
* For each function, determine which parameters flow to sinks.
|
|
13
|
+
* This enables interprocedural taint: processInput(req.body) → exec() is now visible.
|
|
14
|
+
*/
|
|
15
|
+
export function buildInternalSinkMap(sourceFile) {
|
|
16
|
+
const sinkMap = new Map();
|
|
17
|
+
const allFns = [];
|
|
18
|
+
for (const fn of sourceFile.getFunctions()) {
|
|
19
|
+
const name = fn.getName();
|
|
20
|
+
if (name)
|
|
21
|
+
allFns.push({ name, node: fn });
|
|
22
|
+
}
|
|
23
|
+
for (const stmt of sourceFile.getVariableStatements()) {
|
|
24
|
+
for (const decl of stmt.getDeclarations()) {
|
|
25
|
+
const init = decl.getInitializer();
|
|
26
|
+
if (init && (init.getKindName() === 'ArrowFunction' || init.getKindName() === 'FunctionExpression')) {
|
|
27
|
+
allFns.push({ name: decl.getName(), node: init });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const { name, node: fn } of allFns) {
|
|
32
|
+
const params = fn.getParameters();
|
|
33
|
+
const body = fn.getBody();
|
|
34
|
+
if (!body || params.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
// Collect all calls in the body that hit a known sink
|
|
37
|
+
const calls = [];
|
|
38
|
+
body.forEachDescendant((n) => {
|
|
39
|
+
if (n.getKindName() === 'CallExpression')
|
|
40
|
+
calls.push(n);
|
|
41
|
+
});
|
|
42
|
+
const taintedParamIndices = new Set();
|
|
43
|
+
const sinkCategories = new Map();
|
|
44
|
+
for (const call of calls) {
|
|
45
|
+
const calleeName = getCalleeBaseName(call);
|
|
46
|
+
const sinkDef = SINK_NAMES.get(calleeName);
|
|
47
|
+
if (!sinkDef)
|
|
48
|
+
continue;
|
|
49
|
+
// Check which parameter names appear in the sink's arguments
|
|
50
|
+
for (const arg of call.getArguments()) {
|
|
51
|
+
const argText = arg.getText();
|
|
52
|
+
for (let i = 0; i < params.length; i++) {
|
|
53
|
+
const paramName = params[i].getName();
|
|
54
|
+
if (argText === paramName || argText.startsWith(`${paramName}.`) || argText.startsWith(`${paramName}[`)) {
|
|
55
|
+
taintedParamIndices.add(i);
|
|
56
|
+
if (!sinkCategories.has(i))
|
|
57
|
+
sinkCategories.set(i, new Set());
|
|
58
|
+
sinkCategories.get(i).add(sinkDef);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Also check template literal arguments
|
|
63
|
+
for (const arg of call.getArguments()) {
|
|
64
|
+
if (arg.getKindName() === 'TemplateExpression') {
|
|
65
|
+
for (const tplSpan of arg.getTemplateSpans()) {
|
|
66
|
+
const expr = tplSpan.getExpression();
|
|
67
|
+
const exprText = expr.getText();
|
|
68
|
+
for (let i = 0; i < params.length; i++) {
|
|
69
|
+
const paramName = params[i].getName();
|
|
70
|
+
if (exprText === paramName || exprText.startsWith(`${paramName}.`)) {
|
|
71
|
+
taintedParamIndices.add(i);
|
|
72
|
+
if (!sinkCategories.has(i))
|
|
73
|
+
sinkCategories.set(i, new Set());
|
|
74
|
+
sinkCategories.get(i).add(sinkDef);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (taintedParamIndices.size > 0) {
|
|
82
|
+
sinkMap.set(name, { name, taintedParamIndices, sinkCategories });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return sinkMap;
|
|
86
|
+
}
|
|
87
|
+
// ── Main AST Analysis ───────────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* AST-based taint analysis — walks real ts-morph AST nodes instead of regex on strings.
|
|
90
|
+
* Handles destructuring, method chains, computed property access.
|
|
91
|
+
*/
|
|
92
|
+
export function analyzeTaintAST(_inferred, filePath, sourceFile) {
|
|
93
|
+
const results = [];
|
|
94
|
+
// Build intra-file call graph: which internal functions contain sinks?
|
|
95
|
+
const internalSinkMap = buildInternalSinkMap(sourceFile);
|
|
96
|
+
// Collect all function-like AST nodes from the SourceFile
|
|
97
|
+
const allFns = [];
|
|
98
|
+
for (const fn of sourceFile.getFunctions())
|
|
99
|
+
allFns.push({ node: fn, startLine: fn.getStartLineNumber() });
|
|
100
|
+
for (const stmt of sourceFile.getVariableStatements()) {
|
|
101
|
+
for (const decl of stmt.getDeclarations()) {
|
|
102
|
+
const init = decl.getInitializer();
|
|
103
|
+
if (init) {
|
|
104
|
+
const initKind = init.getKindName();
|
|
105
|
+
if (initKind === 'ArrowFunction' || initKind === 'FunctionExpression') {
|
|
106
|
+
allFns.push({ node: init, startLine: stmt.getStartLineNumber() });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
for (const cls of sourceFile.getClasses()) {
|
|
112
|
+
for (const method of cls.getMethods()) {
|
|
113
|
+
allFns.push({ node: method, startLine: method.getStartLineNumber() });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const { node: fn, startLine } of allFns) {
|
|
117
|
+
const params = fn.getParameters();
|
|
118
|
+
const fnName = 'getName' in fn && typeof fn.getName === 'function' ? fn.getName() || 'anonymous' : 'anonymous';
|
|
119
|
+
// Step 1: Classify params as tainted using type info
|
|
120
|
+
const taintedParams = [];
|
|
121
|
+
for (const param of params) {
|
|
122
|
+
const name = param.getName();
|
|
123
|
+
const typeText = param.getType().getText(param);
|
|
124
|
+
if (HTTP_PARAM_NAMES.test(name) || HTTP_PARAM_TYPES.test(typeText)) {
|
|
125
|
+
taintedParams.push({ name, origin: `${name} (HTTP input)` });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (taintedParams.length === 0)
|
|
129
|
+
continue;
|
|
130
|
+
// Step 2: AST-based taint propagation through the function body
|
|
131
|
+
const body = fn.getBody();
|
|
132
|
+
if (!body)
|
|
133
|
+
continue;
|
|
134
|
+
const taintedNames = new Set(taintedParams.map((p) => p.name));
|
|
135
|
+
const taintedVars = new Map();
|
|
136
|
+
for (const p of taintedParams)
|
|
137
|
+
taintedVars.set(p.name, p);
|
|
138
|
+
// Walk ALL variable declarations including nested scopes (if/for/while)
|
|
139
|
+
// forEachDescendant visits in document order = parent-before-child
|
|
140
|
+
const varDecls = [];
|
|
141
|
+
body.forEachDescendant((node) => {
|
|
142
|
+
if (node.getKind() === SyntaxKind.VariableDeclaration) {
|
|
143
|
+
varDecls.push(node);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// Multiple passes to handle forward dependencies (max 3 hops)
|
|
147
|
+
for (let hop = 0; hop < 3; hop++) {
|
|
148
|
+
for (const decl of varDecls) {
|
|
149
|
+
const nameNode = decl.getNameNode();
|
|
150
|
+
const nameKind = nameNode.getKindName();
|
|
151
|
+
// Simple name binding: const id = parseInt(req.body.id)
|
|
152
|
+
if (nameKind === 'Identifier') {
|
|
153
|
+
const declName = nameNode.getText();
|
|
154
|
+
if (taintedNames.has(declName))
|
|
155
|
+
continue;
|
|
156
|
+
const init = decl.getInitializer();
|
|
157
|
+
if (!init)
|
|
158
|
+
continue;
|
|
159
|
+
if (astExprRefersToTainted(init, taintedNames)) {
|
|
160
|
+
taintedNames.add(declName);
|
|
161
|
+
const srcName = findTaintedIdentifier(init, taintedNames);
|
|
162
|
+
const srcVar = srcName ? taintedVars.get(srcName) : undefined;
|
|
163
|
+
const srcOrigin = srcVar?.origin;
|
|
164
|
+
taintedVars.set(declName, { name: declName, origin: srcOrigin || 'derived' });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Object destructuring: const { x, y } = taintedObj
|
|
168
|
+
if (nameKind === 'ObjectBindingPattern') {
|
|
169
|
+
const init = decl.getInitializer();
|
|
170
|
+
if (!init || !astExprRefersToTainted(init, taintedNames))
|
|
171
|
+
continue;
|
|
172
|
+
const srcName = findTaintedIdentifier(init, taintedNames);
|
|
173
|
+
const srcVar2 = srcName ? taintedVars.get(srcName) : undefined;
|
|
174
|
+
const srcOrigin = srcVar2?.origin;
|
|
175
|
+
for (const element of nameNode.getElements()) {
|
|
176
|
+
const elName = element.getName();
|
|
177
|
+
if (!taintedNames.has(elName)) {
|
|
178
|
+
taintedNames.add(elName);
|
|
179
|
+
taintedVars.set(elName, { name: elName, origin: srcOrigin || 'destructured' });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Array destructuring: const [a, b] = taintedArr
|
|
184
|
+
if (nameKind === 'ArrayBindingPattern') {
|
|
185
|
+
const init = decl.getInitializer();
|
|
186
|
+
if (!init || !astExprRefersToTainted(init, taintedNames))
|
|
187
|
+
continue;
|
|
188
|
+
const srcName = findTaintedIdentifier(init, taintedNames);
|
|
189
|
+
const srcVar3 = srcName ? taintedVars.get(srcName) : undefined;
|
|
190
|
+
const srcOrigin = srcVar3?.origin;
|
|
191
|
+
for (const element of nameNode.getElements()) {
|
|
192
|
+
if (element.getKindName() === 'BindingElement') {
|
|
193
|
+
const elName = element.getName();
|
|
194
|
+
if (!taintedNames.has(elName)) {
|
|
195
|
+
taintedNames.add(elName);
|
|
196
|
+
taintedVars.set(elName, { name: elName, origin: srcOrigin || 'destructured' });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Step 3: Find sinks via AST CallExpression walk
|
|
204
|
+
const sinks = [];
|
|
205
|
+
const calls = [];
|
|
206
|
+
body.forEachDescendant((n) => {
|
|
207
|
+
if (n.getKindName() === 'CallExpression')
|
|
208
|
+
calls.push(n);
|
|
209
|
+
});
|
|
210
|
+
for (const call of calls) {
|
|
211
|
+
const calleeName = getCalleeBaseName(call);
|
|
212
|
+
const sinkDef = SINK_NAMES.get(calleeName);
|
|
213
|
+
if (!sinkDef)
|
|
214
|
+
continue;
|
|
215
|
+
// Check if any argument references a tainted variable
|
|
216
|
+
for (const arg of call.getArguments()) {
|
|
217
|
+
const taintedArg = findTaintedIdentifier(arg, taintedNames);
|
|
218
|
+
if (taintedArg) {
|
|
219
|
+
sinks.push({
|
|
220
|
+
name: calleeName,
|
|
221
|
+
category: sinkDef,
|
|
222
|
+
taintedArg,
|
|
223
|
+
line: call.getStartLineNumber(),
|
|
224
|
+
});
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Also check template literal arguments
|
|
229
|
+
const templateArgs = call.getArguments().filter((a) => {
|
|
230
|
+
const k = a.getKindName();
|
|
231
|
+
return k === 'TemplateExpression' || k === 'NoSubstitutionTemplateLiteral';
|
|
232
|
+
});
|
|
233
|
+
for (const tpl of templateArgs) {
|
|
234
|
+
if (tpl.getKindName() === 'TemplateExpression') {
|
|
235
|
+
for (const span of tpl.getTemplateSpans()) {
|
|
236
|
+
const expr = span.getExpression();
|
|
237
|
+
const taintedArg = findTaintedIdentifier(expr, taintedNames);
|
|
238
|
+
if (taintedArg) {
|
|
239
|
+
sinks.push({
|
|
240
|
+
name: `${calleeName} (template)`,
|
|
241
|
+
category: sinkDef,
|
|
242
|
+
taintedArg,
|
|
243
|
+
line: call.getStartLineNumber(),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Step 3b: Interprocedural — check calls to internal functions that contain sinks
|
|
251
|
+
for (const call of calls) {
|
|
252
|
+
const calleeName = getCalleeBaseName(call);
|
|
253
|
+
// Skip if it's already a known sink (handled above)
|
|
254
|
+
if (SINK_NAMES.has(calleeName))
|
|
255
|
+
continue;
|
|
256
|
+
const internalFn = internalSinkMap.get(calleeName);
|
|
257
|
+
if (!internalFn)
|
|
258
|
+
continue;
|
|
259
|
+
// Check if tainted data is passed to a parameter that reaches a sink
|
|
260
|
+
const callArgs = call.getArguments();
|
|
261
|
+
for (const [paramIdx, categories] of internalFn.sinkCategories) {
|
|
262
|
+
if (paramIdx >= callArgs.length)
|
|
263
|
+
continue;
|
|
264
|
+
const arg = callArgs[paramIdx];
|
|
265
|
+
const taintedArg = findTaintedIdentifier(arg, taintedNames);
|
|
266
|
+
if (taintedArg) {
|
|
267
|
+
// Emit one sink per category (a param may reach both exec() and query())
|
|
268
|
+
for (const sinkCategory of categories) {
|
|
269
|
+
sinks.push({
|
|
270
|
+
name: `${calleeName} → sink`,
|
|
271
|
+
category: sinkCategory,
|
|
272
|
+
taintedArg,
|
|
273
|
+
line: call.getStartLineNumber(),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (sinks.length === 0)
|
|
280
|
+
continue;
|
|
281
|
+
// Step 4: Check for sanitizers (AST-based)
|
|
282
|
+
const foundSanitizers = findSanitizersAST(body, taintedNames);
|
|
283
|
+
// Build paths
|
|
284
|
+
const paths = [];
|
|
285
|
+
for (const sink of sinks) {
|
|
286
|
+
const source = taintedVars.get(sink.taintedArg) || taintedParams[0];
|
|
287
|
+
// Subtree matching: sanitize(req.query) covers req.query.id but not req.body.cmd
|
|
288
|
+
// parseInt(req.query.id) does NOT cover exec(req) — only the specific property is safe
|
|
289
|
+
const sanitizer = foundSanitizers.find((s) => {
|
|
290
|
+
for (const sv of s.sanitizedVars) {
|
|
291
|
+
if (sv === sink.taintedArg)
|
|
292
|
+
return true;
|
|
293
|
+
// Sanitized path is a prefix → covers all sub-properties
|
|
294
|
+
if (sink.taintedArg.startsWith(`${sv}.`))
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
});
|
|
299
|
+
const hasSanitizer = sanitizer != null;
|
|
300
|
+
const sufficient = sanitizer != null ? isSanitizerSufficient(sanitizer.name, sink.category) : false;
|
|
301
|
+
paths.push({
|
|
302
|
+
source,
|
|
303
|
+
sink,
|
|
304
|
+
sanitized: hasSanitizer && sufficient,
|
|
305
|
+
sanitizer: sanitizer?.name,
|
|
306
|
+
insufficientSanitizer: hasSanitizer && !sufficient ? sanitizer.name : undefined,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (paths.length > 0) {
|
|
310
|
+
results.push({ fnName, filePath, startLine, paths });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return results;
|
|
314
|
+
}
|
|
315
|
+
// ── AST Helpers ─────────────────────────────────────────────────────────
|
|
316
|
+
/** Check if an expression references any tainted variable name */
|
|
317
|
+
function astExprRefersToTainted(expr, taintedNames) {
|
|
318
|
+
const k = expr.getKindName();
|
|
319
|
+
if (k === 'Identifier' && taintedNames.has(expr.getText()))
|
|
320
|
+
return true;
|
|
321
|
+
if (k === 'PropertyAccessExpression') {
|
|
322
|
+
return astExprRefersToTainted(expr.getExpression(), taintedNames);
|
|
323
|
+
}
|
|
324
|
+
if (k === 'ElementAccessExpression') {
|
|
325
|
+
return astExprRefersToTainted(expr.getExpression(), taintedNames);
|
|
326
|
+
}
|
|
327
|
+
if (k === 'CallExpression') {
|
|
328
|
+
if (astExprRefersToTainted(expr.getExpression(), taintedNames))
|
|
329
|
+
return true;
|
|
330
|
+
for (const arg of expr.getArguments()) {
|
|
331
|
+
if (astExprRefersToTainted(arg, taintedNames))
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
if (k === 'AwaitExpression') {
|
|
337
|
+
return astExprRefersToTainted(expr.getExpression(), taintedNames);
|
|
338
|
+
}
|
|
339
|
+
// Check all children for complex expressions
|
|
340
|
+
for (const child of expr.getChildren()) {
|
|
341
|
+
if (astExprRefersToTainted(child, taintedNames))
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
/** Get the base name of a callee (e.g., exec from child_process.exec, or db.query) */
|
|
347
|
+
function getCalleeBaseName(call) {
|
|
348
|
+
const expr = call.getExpression();
|
|
349
|
+
const k = expr.getKindName();
|
|
350
|
+
if (k === 'Identifier')
|
|
351
|
+
return expr.getText();
|
|
352
|
+
if (k === 'PropertyAccessExpression')
|
|
353
|
+
return expr.getName();
|
|
354
|
+
return '';
|
|
355
|
+
}
|
|
356
|
+
/** Get the full static access path (e.g., req.query.id). Returns undefined for dynamic access. */
|
|
357
|
+
function getStaticAccessPath(expr) {
|
|
358
|
+
const k = expr.getKindName();
|
|
359
|
+
if (k === 'Identifier')
|
|
360
|
+
return expr.getText();
|
|
361
|
+
if (k === 'PropertyAccessExpression') {
|
|
362
|
+
const obj = getStaticAccessPath(expr.getExpression());
|
|
363
|
+
if (obj)
|
|
364
|
+
return `${obj}.${expr.getName()}`;
|
|
365
|
+
}
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
/** Find the first tainted identifier in an expression tree */
|
|
369
|
+
function findTaintedIdentifier(expr, taintedNames) {
|
|
370
|
+
const k = expr.getKindName();
|
|
371
|
+
if (k === 'Identifier' && taintedNames.has(expr.getText()))
|
|
372
|
+
return expr.getText();
|
|
373
|
+
if (k === 'PropertyAccessExpression') {
|
|
374
|
+
return findTaintedIdentifier(expr.getExpression(), taintedNames);
|
|
375
|
+
}
|
|
376
|
+
// Check binary expressions (string concatenation: 'cmd ' + userInput)
|
|
377
|
+
if (k === 'BinaryExpression') {
|
|
378
|
+
return (findTaintedIdentifier(expr.getLeft(), taintedNames) ||
|
|
379
|
+
findTaintedIdentifier(expr.getRight(), taintedNames));
|
|
380
|
+
}
|
|
381
|
+
for (const child of expr.getChildren()) {
|
|
382
|
+
const found = findTaintedIdentifier(child, taintedNames);
|
|
383
|
+
if (found)
|
|
384
|
+
return found;
|
|
385
|
+
}
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
/** AST-based sanitizer detection */
|
|
389
|
+
function findSanitizersAST(body, taintedNames) {
|
|
390
|
+
const sanitizers = [];
|
|
391
|
+
const allCalls = [];
|
|
392
|
+
body.forEachDescendant((n) => {
|
|
393
|
+
if (n.getKindName() === 'CallExpression')
|
|
394
|
+
allCalls.push(n);
|
|
395
|
+
});
|
|
396
|
+
for (const call of allCalls) {
|
|
397
|
+
const calleeName = getCalleeBaseName(call);
|
|
398
|
+
const matchedSanitizer = SANITIZER_PATTERN_NAMES.find((s) => calleeName.includes(s));
|
|
399
|
+
if (!matchedSanitizer)
|
|
400
|
+
continue;
|
|
401
|
+
// Track which tainted vars are sanitized by this call
|
|
402
|
+
const sanitizedVars = new Set();
|
|
403
|
+
for (const arg of call.getArguments()) {
|
|
404
|
+
// Track the FULL access path so parseInt(req.query.id) sanitizes 'req.query.id', not 'req'
|
|
405
|
+
const fullPath = getStaticAccessPath(arg);
|
|
406
|
+
if (fullPath && findTaintedIdentifier(arg, taintedNames)) {
|
|
407
|
+
sanitizedVars.add(fullPath);
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
const tainted = findTaintedIdentifier(arg, taintedNames);
|
|
411
|
+
if (tainted)
|
|
412
|
+
sanitizedVars.add(tainted);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Also check if the result is assigned to a variable (replacing the tainted value)
|
|
416
|
+
const parent = call.getParent();
|
|
417
|
+
if (parent && parent.getKindName() === 'VariableDeclaration') {
|
|
418
|
+
const declName = parent.getName();
|
|
419
|
+
sanitizedVars.add(declName);
|
|
420
|
+
}
|
|
421
|
+
if (sanitizedVars.size > 0) {
|
|
422
|
+
sanitizers.push({ name: matchedSanitizer, sanitizedVars });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return sanitizers;
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=taint-ast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taint-ast.js","sourceRoot":"","sources":["../src/taint-ast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — cross-file analysis.
|
|
3
|
+
*
|
|
4
|
+
* Traces tainted data across import boundaries:
|
|
5
|
+
* handler(req) → importedFn(req.body) → exec() in another file.
|
|
6
|
+
*/
|
|
7
|
+
import type { CrossFileTaintResult, ExportedFunction } from './taint-types.js';
|
|
8
|
+
import type { InferResult } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Build a map of exported functions across all files.
|
|
11
|
+
* Maps "filePath::fnName" → ExportedFunction with sink info.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildExportMap(inferredPerFile: Map<string, InferResult[]>): Map<string, ExportedFunction>;
|
|
14
|
+
/**
|
|
15
|
+
* Build import→function resolution map.
|
|
16
|
+
* Maps "importingFile::importedName" → absolute file path of the definition.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildImportMap(inferredPerFile: Map<string, InferResult[]>, graphImports: Map<string, string[]>): Map<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Cross-file taint analysis.
|
|
21
|
+
*
|
|
22
|
+
* For each handler function with tainted params:
|
|
23
|
+
* 1. Find calls to imported functions in the handler body
|
|
24
|
+
* 2. Check if tainted data is passed as an argument
|
|
25
|
+
* 3. Look up the target function — does it have a dangerous sink?
|
|
26
|
+
* 4. If yes and no sanitizer in between → cross-file taint path
|
|
27
|
+
*/
|
|
28
|
+
export declare function analyzeTaintCrossFile(inferredPerFile: Map<string, InferResult[]>, graphImports: Map<string, string[]>): CrossFileTaintResult[];
|