@kernlang/review 3.1.6 → 3.1.8
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/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 +210 -121
- 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.js +23 -19
- package/dist/rules/cli.js.map +1 -1
- 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.js +53 -19
- package/dist/rules/fastapi.js.map +1 -1
- package/dist/rules/ground-layer.js +3 -3
- package/dist/rules/ground-layer.js.map +1 -1
- package/dist/rules/index.js +574 -105
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/ink.js +9 -8
- package/dist/rules/ink.js.map +1 -1
- 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.js +17 -5
- package/dist/rules/terminal.js.map +1 -1
- 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 +2 -2
|
@@ -0,0 +1,174 @@
|
|
|
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 { classifyParams, detectSanitizers, findClosingParen, findTaintedSinks, propagateTaint } from './taint-regex.js';
|
|
8
|
+
// ── Export Map ───────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Build a map of exported functions across all files.
|
|
11
|
+
* Maps "filePath::fnName" → ExportedFunction with sink info.
|
|
12
|
+
*/
|
|
13
|
+
export function buildExportMap(inferredPerFile) {
|
|
14
|
+
const exportMap = new Map();
|
|
15
|
+
for (const [filePath, inferred] of inferredPerFile) {
|
|
16
|
+
for (const r of inferred) {
|
|
17
|
+
if (r.node.type !== 'fn')
|
|
18
|
+
continue;
|
|
19
|
+
const fnName = r.node.props?.name || '';
|
|
20
|
+
if (!fnName)
|
|
21
|
+
continue;
|
|
22
|
+
// Check if function is exported (absence of export='false' means exported)
|
|
23
|
+
const isExported = r.node.props?.export !== 'false';
|
|
24
|
+
if (!isExported)
|
|
25
|
+
continue;
|
|
26
|
+
const params = r.node.props?.params || '';
|
|
27
|
+
const handler = r.node.children?.find((c) => c.type === 'handler');
|
|
28
|
+
const code = handler?.props?.code || '';
|
|
29
|
+
// Check if the function body contains dangerous sinks
|
|
30
|
+
const sinks = [];
|
|
31
|
+
if (code) {
|
|
32
|
+
const dummyTaint = [];
|
|
33
|
+
// Parse params to get variable names for sink detection
|
|
34
|
+
const paramNames = params
|
|
35
|
+
.split(',')
|
|
36
|
+
.map((p) => p.trim().split(':')[0]?.trim())
|
|
37
|
+
.filter(Boolean);
|
|
38
|
+
for (const name of paramNames) {
|
|
39
|
+
dummyTaint.push({ name, origin: `param:${name}` });
|
|
40
|
+
}
|
|
41
|
+
if (dummyTaint.length > 0) {
|
|
42
|
+
sinks.push(...findTaintedSinks(code, dummyTaint));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exportMap.set(`${filePath}::${fnName}`, {
|
|
46
|
+
filePath,
|
|
47
|
+
fnName,
|
|
48
|
+
params,
|
|
49
|
+
hasSink: sinks.length > 0,
|
|
50
|
+
sinks,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return exportMap;
|
|
55
|
+
}
|
|
56
|
+
// ── Import Map ──────────────────────────────────────────────────────────
|
|
57
|
+
/**
|
|
58
|
+
* Build import→function resolution map.
|
|
59
|
+
* Maps "importingFile::importedName" → absolute file path of the definition.
|
|
60
|
+
*/
|
|
61
|
+
export function buildImportMap(inferredPerFile, graphImports) {
|
|
62
|
+
const importMap = new Map();
|
|
63
|
+
for (const [filePath, inferred] of inferredPerFile) {
|
|
64
|
+
const resolvedImports = graphImports.get(filePath) || [];
|
|
65
|
+
for (const r of inferred) {
|
|
66
|
+
if (r.node.type !== 'import')
|
|
67
|
+
continue;
|
|
68
|
+
const from = r.node.props?.from || '';
|
|
69
|
+
const names = r.node.props?.names || '';
|
|
70
|
+
const defaultImport = r.node.props?.default || '';
|
|
71
|
+
if (!from)
|
|
72
|
+
continue;
|
|
73
|
+
// Find the resolved path for this import specifier
|
|
74
|
+
const resolvedPath = resolvedImports.find((p) => p.includes(from.replace(/^\.\//, '').replace(/\.(js|ts|tsx)$/, '')));
|
|
75
|
+
if (!resolvedPath)
|
|
76
|
+
continue;
|
|
77
|
+
// Map each imported name to its resolved file
|
|
78
|
+
if (names) {
|
|
79
|
+
for (const name of names.split(',').map((n) => n.trim())) {
|
|
80
|
+
if (name)
|
|
81
|
+
importMap.set(`${filePath}::${name}`, resolvedPath);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (defaultImport) {
|
|
85
|
+
importMap.set(`${filePath}::${defaultImport}`, resolvedPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return importMap;
|
|
90
|
+
}
|
|
91
|
+
// ── Cross-File Analysis ─────────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Cross-file taint analysis.
|
|
94
|
+
*
|
|
95
|
+
* For each handler function with tainted params:
|
|
96
|
+
* 1. Find calls to imported functions in the handler body
|
|
97
|
+
* 2. Check if tainted data is passed as an argument
|
|
98
|
+
* 3. Look up the target function — does it have a dangerous sink?
|
|
99
|
+
* 4. If yes and no sanitizer in between → cross-file taint path
|
|
100
|
+
*/
|
|
101
|
+
export function analyzeTaintCrossFile(inferredPerFile, graphImports) {
|
|
102
|
+
const exportMap = buildExportMap(inferredPerFile);
|
|
103
|
+
const importMap = buildImportMap(inferredPerFile, graphImports);
|
|
104
|
+
const results = [];
|
|
105
|
+
for (const [filePath, inferred] of inferredPerFile) {
|
|
106
|
+
for (const r of inferred) {
|
|
107
|
+
if (r.node.type !== 'fn')
|
|
108
|
+
continue;
|
|
109
|
+
const fnName = r.node.props?.name || 'anonymous';
|
|
110
|
+
const paramsStr = r.node.props?.params || '';
|
|
111
|
+
const handler = r.node.children?.find((c) => c.type === 'handler');
|
|
112
|
+
const code = handler?.props?.code || '';
|
|
113
|
+
if (!code)
|
|
114
|
+
continue;
|
|
115
|
+
// Only analyze functions with tainted params
|
|
116
|
+
const taintedParams = classifyParams(paramsStr);
|
|
117
|
+
if (taintedParams.length === 0)
|
|
118
|
+
continue;
|
|
119
|
+
const taintedVars = propagateTaint(code, taintedParams);
|
|
120
|
+
const taintedNames = new Set(taintedVars.map((v) => v.name));
|
|
121
|
+
// Find calls to imported functions: importedFn(taintedVar)
|
|
122
|
+
const callRegex = /\b(\w+)\s*\(/g;
|
|
123
|
+
let callMatch;
|
|
124
|
+
while ((callMatch = callRegex.exec(code)) !== null) {
|
|
125
|
+
const calledFn = callMatch[0].replace(/\s*\($/, '');
|
|
126
|
+
// Is this an imported function?
|
|
127
|
+
const resolvedFile = importMap.get(`${filePath}::${calledFn}`);
|
|
128
|
+
if (!resolvedFile)
|
|
129
|
+
continue;
|
|
130
|
+
// Does the target have dangerous sinks?
|
|
131
|
+
const targetFn = exportMap.get(`${resolvedFile}::${calledFn}`);
|
|
132
|
+
if (!targetFn?.hasSink)
|
|
133
|
+
continue;
|
|
134
|
+
// Extract arguments passed to this call
|
|
135
|
+
const callStart = callMatch.index + callMatch[0].length;
|
|
136
|
+
const parenEnd = findClosingParen(code, callStart);
|
|
137
|
+
const argText = code.slice(callStart, parenEnd);
|
|
138
|
+
// Check if any tainted variable is passed as argument
|
|
139
|
+
const taintedArgs = [];
|
|
140
|
+
for (const tName of taintedNames) {
|
|
141
|
+
if (new RegExp(`\\b${tName}\\b`).test(argText)) {
|
|
142
|
+
taintedArgs.push(tName);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (taintedArgs.length === 0)
|
|
146
|
+
continue;
|
|
147
|
+
// Check for sanitizers between the taint and the call
|
|
148
|
+
const beforeCall = code.slice(0, callMatch.index);
|
|
149
|
+
const foundSanitizers = detectSanitizers(beforeCall);
|
|
150
|
+
const hasSanitizer = taintedArgs.some((arg) => foundSanitizers.some((s) => new RegExp(`\\b${arg}\\b`).test(s.context)));
|
|
151
|
+
if (hasSanitizer)
|
|
152
|
+
continue; // Sanitized before passing to callee
|
|
153
|
+
// Found cross-file taint path
|
|
154
|
+
for (const sink of targetFn.sinks) {
|
|
155
|
+
const source = taintedVars.find((v) => taintedArgs.includes(v.name));
|
|
156
|
+
if (!source)
|
|
157
|
+
continue;
|
|
158
|
+
results.push({
|
|
159
|
+
callerFile: filePath,
|
|
160
|
+
callerFn: fnName,
|
|
161
|
+
callerLine: r.startLine,
|
|
162
|
+
calleeFile: resolvedFile,
|
|
163
|
+
calleeFn: calledFn,
|
|
164
|
+
taintedArgs,
|
|
165
|
+
sinkInCallee: sink,
|
|
166
|
+
source,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return results;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=taint-crossfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taint-crossfile.js","sourceRoot":"","sources":["../src/taint-crossfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — unified finding generation.
|
|
3
|
+
*
|
|
4
|
+
* Converts TaintResult and CrossFileTaintResult into ReviewFinding[].
|
|
5
|
+
* Shared category labels and suggestion logic eliminates duplication.
|
|
6
|
+
*/
|
|
7
|
+
import type { CrossFileTaintResult, TaintResult, TaintSink } from './taint-types.js';
|
|
8
|
+
import type { ReviewFinding } from './types.js';
|
|
9
|
+
export declare function getSuggestion(category: TaintSink['category']): string;
|
|
10
|
+
/**
|
|
11
|
+
* Convert taint results into ReviewFinding[] for the unified pipeline.
|
|
12
|
+
*/
|
|
13
|
+
export declare function taintToFindings(results: TaintResult[]): ReviewFinding[];
|
|
14
|
+
/**
|
|
15
|
+
* Convert cross-file taint results into ReviewFinding[].
|
|
16
|
+
*/
|
|
17
|
+
export declare function crossFileTaintToFindings(results: CrossFileTaintResult[]): ReviewFinding[];
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — unified finding generation.
|
|
3
|
+
*
|
|
4
|
+
* Converts TaintResult and CrossFileTaintResult into ReviewFinding[].
|
|
5
|
+
* Shared category labels and suggestion logic eliminates duplication.
|
|
6
|
+
*/
|
|
7
|
+
import { createFingerprint } from './types.js';
|
|
8
|
+
// ── Shared Constants ────────────────────────────────────────────────────
|
|
9
|
+
const categoryLabels = {
|
|
10
|
+
command: 'command injection',
|
|
11
|
+
fs: 'path traversal / file write',
|
|
12
|
+
sql: 'SQL injection',
|
|
13
|
+
redirect: 'open redirect',
|
|
14
|
+
eval: 'code injection',
|
|
15
|
+
template: 'template injection',
|
|
16
|
+
codegen: 'code generation injection',
|
|
17
|
+
};
|
|
18
|
+
export function getSuggestion(category) {
|
|
19
|
+
switch (category) {
|
|
20
|
+
case 'command':
|
|
21
|
+
return 'Use spawn() with array arguments, or validate/escape input before passing to exec()';
|
|
22
|
+
case 'fs':
|
|
23
|
+
return 'Use path.resolve() + path.normalize() and verify the result stays within allowed directory';
|
|
24
|
+
case 'sql':
|
|
25
|
+
return 'Use parameterized queries ($1, ?) instead of string interpolation';
|
|
26
|
+
case 'redirect':
|
|
27
|
+
return 'Validate redirect URL against an allowlist of safe destinations';
|
|
28
|
+
case 'eval':
|
|
29
|
+
return 'Never pass user input to eval() or new Function() — use safe alternatives';
|
|
30
|
+
case 'template':
|
|
31
|
+
return 'Sanitize user input before embedding in templates';
|
|
32
|
+
case 'codegen':
|
|
33
|
+
return 'Validate type and format of external values before interpolating into generated source code (e.g., parseInt for numeric values)';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ── Intra-File Findings ─────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Convert taint results into ReviewFinding[] for the unified pipeline.
|
|
39
|
+
*/
|
|
40
|
+
export function taintToFindings(results) {
|
|
41
|
+
const findings = [];
|
|
42
|
+
for (const r of results) {
|
|
43
|
+
// Report unsanitized paths AND insufficient sanitizer paths
|
|
44
|
+
const reportable = r.paths.filter((p) => !p.sanitized);
|
|
45
|
+
if (reportable.length === 0)
|
|
46
|
+
continue;
|
|
47
|
+
for (const path of reportable) {
|
|
48
|
+
const severity = path.sink.category === 'command' || path.sink.category === 'eval'
|
|
49
|
+
? 'error'
|
|
50
|
+
: path.sink.category === 'codegen'
|
|
51
|
+
? 'warning' // codegen injection: external values in generated source — validate type/format
|
|
52
|
+
: 'warning';
|
|
53
|
+
const primarySpan = {
|
|
54
|
+
file: r.filePath,
|
|
55
|
+
startLine: r.startLine,
|
|
56
|
+
startCol: 1,
|
|
57
|
+
endLine: r.startLine,
|
|
58
|
+
endCol: 1,
|
|
59
|
+
};
|
|
60
|
+
if (path.insufficientSanitizer) {
|
|
61
|
+
// Sanitizer present but wrong for this sink type
|
|
62
|
+
findings.push({
|
|
63
|
+
source: 'kern',
|
|
64
|
+
ruleId: `taint-insufficient-sanitizer`,
|
|
65
|
+
severity,
|
|
66
|
+
category: 'bug',
|
|
67
|
+
message: `Insufficient sanitizer: '${path.insufficientSanitizer}' does not protect against ${categoryLabels[path.sink.category]}. ` +
|
|
68
|
+
`${path.source.origin} → ${path.sink.name}() is still exploitable.`,
|
|
69
|
+
primarySpan,
|
|
70
|
+
suggestion: `${path.insufficientSanitizer} is not sufficient for ${path.sink.category} sinks. ${getSuggestion(path.sink.category)}`,
|
|
71
|
+
fingerprint: createFingerprint(`taint-insufficient`, r.startLine, 1),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// No sanitizer at all
|
|
76
|
+
findings.push({
|
|
77
|
+
source: 'kern',
|
|
78
|
+
ruleId: `taint-${path.sink.category}`,
|
|
79
|
+
severity,
|
|
80
|
+
category: 'bug',
|
|
81
|
+
message: `Taint flow: ${path.source.origin} → ${path.sink.name}() — potential ${categoryLabels[path.sink.category]}. ` +
|
|
82
|
+
`Variable '${path.sink.taintedArg}' reaches dangerous sink without sanitization.`,
|
|
83
|
+
primarySpan,
|
|
84
|
+
suggestion: getSuggestion(path.sink.category),
|
|
85
|
+
fingerprint: createFingerprint(`taint-${path.sink.category}`, r.startLine, 1),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return findings;
|
|
91
|
+
}
|
|
92
|
+
// ── Cross-File Findings ─────────────────────────────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Convert cross-file taint results into ReviewFinding[].
|
|
95
|
+
*/
|
|
96
|
+
export function crossFileTaintToFindings(results) {
|
|
97
|
+
const findings = [];
|
|
98
|
+
for (const r of results) {
|
|
99
|
+
const severity = r.sinkInCallee.category === 'command' || r.sinkInCallee.category === 'eval'
|
|
100
|
+
? 'error'
|
|
101
|
+
: 'warning';
|
|
102
|
+
findings.push({
|
|
103
|
+
source: 'kern',
|
|
104
|
+
ruleId: `taint-crossfile-${r.sinkInCallee.category}`,
|
|
105
|
+
severity,
|
|
106
|
+
category: 'bug',
|
|
107
|
+
message: `Cross-file taint: ${r.source.origin} in ${r.callerFn}() → ${r.calleeFn}() → ${r.sinkInCallee.name}(). ` +
|
|
108
|
+
`Tainted data crosses file boundary to reach ${categoryLabels[r.sinkInCallee.category]} sink.`,
|
|
109
|
+
primarySpan: {
|
|
110
|
+
file: r.callerFile,
|
|
111
|
+
startLine: r.callerLine,
|
|
112
|
+
startCol: 1,
|
|
113
|
+
endLine: r.callerLine,
|
|
114
|
+
endCol: 1,
|
|
115
|
+
},
|
|
116
|
+
relatedSpans: [
|
|
117
|
+
{
|
|
118
|
+
file: r.calleeFile,
|
|
119
|
+
startLine: 1,
|
|
120
|
+
startCol: 1,
|
|
121
|
+
endLine: 1,
|
|
122
|
+
endCol: 1,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
suggestion: `Validate '${r.taintedArgs.join(', ')}' before passing to ${r.calleeFn}(). ${getSuggestion(r.sinkInCallee.category)}`,
|
|
126
|
+
fingerprint: createFingerprint(`taint-xfile-${r.sinkInCallee.category}`, r.callerLine, 1),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return findings;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=taint-findings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taint-findings.js","sourceRoot":"","sources":["../src/taint-findings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taint Tracking — Regex-based fallback engine.
|
|
3
|
+
*
|
|
4
|
+
* Used when no ts-morph SourceFile is available.
|
|
5
|
+
* Works on handler body strings from KERN IR nodes.
|
|
6
|
+
*/
|
|
7
|
+
import type { TaintPath, TaintResult, TaintSink, TaintSource } from './taint-types.js';
|
|
8
|
+
import type { InferResult } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Regex-based taint analysis — legacy fallback for when no SourceFile is available.
|
|
11
|
+
*/
|
|
12
|
+
export declare function analyzeTaintRegex(inferred: InferResult[], filePath: string): TaintResult[];
|
|
13
|
+
/**
|
|
14
|
+
* Classify function parameters as tainted or safe.
|
|
15
|
+
*/
|
|
16
|
+
export declare function classifyParams(paramsStr: string): TaintSource[];
|
|
17
|
+
/**
|
|
18
|
+
* Multi-hop taint propagation using worklist algorithm.
|
|
19
|
+
* Propagates until fixed point or configurable depth limit.
|
|
20
|
+
*
|
|
21
|
+
* Handles all assignment patterns:
|
|
22
|
+
* - const b = a
|
|
23
|
+
* - const b = a.trim()
|
|
24
|
+
* - const {x} = obj
|
|
25
|
+
* - let b; b = a
|
|
26
|
+
*
|
|
27
|
+
* @param code - Handler code string
|
|
28
|
+
* @param initialTainted - Set of initially tainted variable names
|
|
29
|
+
* @param maxDepth - Maximum propagation depth (default: 3)
|
|
30
|
+
* @returns Set of all tainted variable names after fixed point or depth limit
|
|
31
|
+
*/
|
|
32
|
+
export declare function propagateTaintMultiHop(code: string, initialTainted: Set<string>, maxDepth?: number): Set<string>;
|
|
33
|
+
interface Assignment {
|
|
34
|
+
lhs: string;
|
|
35
|
+
rhs: string;
|
|
36
|
+
assignId: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function extractAllAssignments(code: string): Assignment[];
|
|
39
|
+
export declare function parseLineAssignments(line: string, lineNum: number): Assignment[];
|
|
40
|
+
export declare function extractDependencies(rhs: string): Set<string>;
|
|
41
|
+
export declare function isCircularAssignment(lhs: string, rhs: string, allAssignments: Assignment[]): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Propagate taint through variable assignments in handler body.
|
|
44
|
+
* Tracks: const x = req.body.foo → x is tainted.
|
|
45
|
+
* Returns all tainted variable names with their origins.
|
|
46
|
+
*/
|
|
47
|
+
export declare function propagateTaint(code: string, params: TaintSource[]): TaintSource[];
|
|
48
|
+
/**
|
|
49
|
+
* Find sink calls that use tainted variables.
|
|
50
|
+
*/
|
|
51
|
+
export declare function findTaintedSinks(code: string, taintedVars: TaintSource[]): TaintSink[];
|
|
52
|
+
/**
|
|
53
|
+
* Build taint paths and check for sanitizers between source and sink.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildPaths(code: string, taintedVars: TaintSource[], sinks: TaintSink[]): TaintPath[];
|
|
56
|
+
export declare function detectSanitizers(code: string): Array<{
|
|
57
|
+
name: string;
|
|
58
|
+
context: string;
|
|
59
|
+
}>;
|
|
60
|
+
export declare function findClosingParen(code: string, start: number): number;
|
|
61
|
+
export {};
|