circle-ir 4.9.10 → 4.9.11
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/analysis/passes/taint-propagation-pass.d.ts.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js +76 -4
- package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
- package/dist/analysis/taint-matcher.d.ts +0 -8
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +105 -3
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analysis/taint-propagation.d.ts.map +1 -1
- package/dist/analysis/taint-propagation.js +15 -0
- package/dist/analysis/taint-propagation.js.map +1 -1
- package/dist/browser/circle-ir.js +91 -7
- package/dist/core/circle-ir-core.cjs +36 -2
- package/dist/core/circle-ir-core.js +36 -2
- package/package.json +1 -1
|
@@ -15056,14 +15056,30 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
15056
15056
|
// regex registry so it's recognized in subscript/var contexts.
|
|
15057
15057
|
{ pattern: /\binput\s*\(/, sourceType: "io_input" }
|
|
15058
15058
|
];
|
|
15059
|
+
function dropCSharpObjectCarriedWaypoints(sinks, calls) {
|
|
15060
|
+
const zeroArgCtors = /* @__PURE__ */ new Set();
|
|
15061
|
+
for (const call of calls) {
|
|
15062
|
+
if (call.is_constructor && call.arguments.length === 0) {
|
|
15063
|
+
zeroArgCtors.add(`${call.location.line}:${call.method_name}`);
|
|
15064
|
+
}
|
|
15065
|
+
}
|
|
15066
|
+
return sinks.filter((sink) => {
|
|
15067
|
+
if (sink.type !== "sql_injection") return true;
|
|
15068
|
+
if (sink.method && zeroArgCtors.has(`${sink.line}:${sink.method}`)) {
|
|
15069
|
+
return false;
|
|
15070
|
+
}
|
|
15071
|
+
return true;
|
|
15072
|
+
});
|
|
15073
|
+
}
|
|
15059
15074
|
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language, code) {
|
|
15060
15075
|
const sourceLines = code !== void 0 ? code.split("\n") : void 0;
|
|
15061
15076
|
const sources = findSources(calls, types, config.sources, sourceLines, language);
|
|
15062
15077
|
let sinkPatterns = expandPromisifyAliases(config.sinks, sourceLines, language);
|
|
15063
15078
|
sinkPatterns = expandIndirectEvalAliases(sinkPatterns, sourceLines, language);
|
|
15064
15079
|
const sinks = findSinks(calls, sinkPatterns, typeHierarchy, language, sourceLines, types);
|
|
15080
|
+
const gatedSinks = language === "csharp" ? dropCSharpObjectCarriedWaypoints(sinks, calls) : sinks;
|
|
15065
15081
|
const sanitizers = findSanitizers(calls, types, config.sanitizers, sourceLines);
|
|
15066
|
-
return { sources, sinks, sanitizers };
|
|
15082
|
+
return { sources, sinks: gatedSinks, sanitizers };
|
|
15067
15083
|
}
|
|
15068
15084
|
function sinkPatternAppliesTo(pattern, language) {
|
|
15069
15085
|
if (language === void 0) return true;
|
|
@@ -15334,7 +15350,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
15334
15350
|
}
|
|
15335
15351
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
15336
15352
|
for (const source of sources) {
|
|
15337
|
-
const key = `${source.line}:${source.type}`;
|
|
15353
|
+
const key = source.type === "interprocedural_param" && source.variable ? `${source.line}:${source.type}:${source.variable}` : `${source.line}:${source.type}`;
|
|
15338
15354
|
const existing = sourceMap.get(key);
|
|
15339
15355
|
if (!existing || source.confidence > existing.confidence) {
|
|
15340
15356
|
sourceMap.set(key, source);
|
|
@@ -15952,6 +15968,15 @@ var CWE_78_RECEIVER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
|
15952
15968
|
// hutool
|
|
15953
15969
|
"RuntimeUtil"
|
|
15954
15970
|
]);
|
|
15971
|
+
function isRegexReceiver(receiver, sourceLines) {
|
|
15972
|
+
const r = (receiver ?? "").trim();
|
|
15973
|
+
if (r.length === 0) return false;
|
|
15974
|
+
if (r.startsWith("/") && /\/[a-z]*$/.test(r)) return true;
|
|
15975
|
+
if (/^(?:new\s+)?RegExp\s*\(/.test(r)) return true;
|
|
15976
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(r) || !sourceLines) return false;
|
|
15977
|
+
const decl = new RegExp(`(?:const|let|var)\\s+${escapeRe(r)}\\s*=\\s*(?:/|(?:new\\s+)?RegExp\\s*\\()`);
|
|
15978
|
+
return sourceLines.some((l) => decl.test(l));
|
|
15979
|
+
}
|
|
15955
15980
|
function isFunctionCallbackArgument(arg) {
|
|
15956
15981
|
if (arg.literal !== null && arg.literal !== void 0) return false;
|
|
15957
15982
|
const expr = (arg.expression ?? "").trim();
|
|
@@ -16134,6 +16159,12 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
|
|
|
16134
16159
|
continue;
|
|
16135
16160
|
}
|
|
16136
16161
|
}
|
|
16162
|
+
if (pattern.type === "command_injection" && call.method_name === "exec" && (language === "javascript" || language === "typescript") && isRegexReceiver(call.receiver, sourceLines)) {
|
|
16163
|
+
continue;
|
|
16164
|
+
}
|
|
16165
|
+
if (pattern.type === "code_injection" && language === "python" && call.method_name === "compile" && call.receiver && call.receiver !== "builtins") {
|
|
16166
|
+
continue;
|
|
16167
|
+
}
|
|
16137
16168
|
if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
|
|
16138
16169
|
continue;
|
|
16139
16170
|
}
|
|
@@ -18784,6 +18815,9 @@ function findInitialTaint(sources, callsByLine, defsByLine) {
|
|
|
18784
18815
|
for (const source of sources) {
|
|
18785
18816
|
const defsOnLine = defsByLine.get(source.line) ?? [];
|
|
18786
18817
|
for (const def of defsOnLine) {
|
|
18818
|
+
if (source.type === "interprocedural_param" && source.variable && def.kind === "param" && def.variable !== source.variable) {
|
|
18819
|
+
continue;
|
|
18820
|
+
}
|
|
18787
18821
|
tainted.push({
|
|
18788
18822
|
variable: def.variable,
|
|
18789
18823
|
defId: def.id,
|
|
@@ -36332,7 +36366,7 @@ var TaintPropagationPass = class {
|
|
|
36332
36366
|
for (const f of paramFlows) {
|
|
36333
36367
|
pushIfNew(f);
|
|
36334
36368
|
}
|
|
36335
|
-
const exprScanFlows = detectExpressionScanFlows(calls, sources, sinks, sanitizers, constProp.unreachableLines, constProp.tainted, ctx.code, ctx.language) ?? [];
|
|
36369
|
+
const exprScanFlows = detectExpressionScanFlows(calls, sources, sinks, sanitizers, constProp.unreachableLines, constProp.tainted, ctx.code, ctx.language, types) ?? [];
|
|
36336
36370
|
for (const f of exprScanFlows) {
|
|
36337
36371
|
if (flowKeys.has(flowKey(f))) continue;
|
|
36338
36372
|
const flowForCheck = {
|
|
@@ -36484,6 +36518,36 @@ var TaintPropagationPass = class {
|
|
|
36484
36518
|
return bestByKey.get(key) === f;
|
|
36485
36519
|
});
|
|
36486
36520
|
}
|
|
36521
|
+
if (ctx.language === "csharp" && finalFlows.length > 1) {
|
|
36522
|
+
const CSHARP_ADO_EXECUTE = /^Execute(?:Reader|NonQuery|Scalar)(?:Async)?$/;
|
|
36523
|
+
const commandTextReceiverByLine = /* @__PURE__ */ new Map();
|
|
36524
|
+
const execLinesByReceiver = /* @__PURE__ */ new Map();
|
|
36525
|
+
for (const call of calls) {
|
|
36526
|
+
const receiver = (call.receiver ?? "").trim();
|
|
36527
|
+
if (!receiver) continue;
|
|
36528
|
+
if (call.method_name === "CommandText") {
|
|
36529
|
+
commandTextReceiverByLine.set(call.location.line, receiver);
|
|
36530
|
+
} else if (CSHARP_ADO_EXECUTE.test(call.method_name)) {
|
|
36531
|
+
const lines = execLinesByReceiver.get(receiver) ?? [];
|
|
36532
|
+
lines.push(call.location.line);
|
|
36533
|
+
execLinesByReceiver.set(receiver, lines);
|
|
36534
|
+
}
|
|
36535
|
+
}
|
|
36536
|
+
if (commandTextReceiverByLine.size > 0) {
|
|
36537
|
+
const reportedSqlSinkLines = new Set(
|
|
36538
|
+
finalFlows.filter((f) => f.sink_type === "sql_injection").map((f) => f.sink_line)
|
|
36539
|
+
);
|
|
36540
|
+
finalFlows = finalFlows.filter((f) => {
|
|
36541
|
+
if (f.sink_type !== "sql_injection") return true;
|
|
36542
|
+
const receiver = commandTextReceiverByLine.get(f.sink_line);
|
|
36543
|
+
if (receiver === void 0) return true;
|
|
36544
|
+
const execLines = execLinesByReceiver.get(receiver) ?? [];
|
|
36545
|
+
return !execLines.some(
|
|
36546
|
+
(line) => line > f.sink_line && reportedSqlSinkLines.has(line)
|
|
36547
|
+
);
|
|
36548
|
+
});
|
|
36549
|
+
}
|
|
36550
|
+
}
|
|
36487
36551
|
return { flows: finalFlows };
|
|
36488
36552
|
}
|
|
36489
36553
|
};
|
|
@@ -36901,7 +36965,7 @@ function isReassignedToLiteralBetween(code, variable, srcLine, sinkLine) {
|
|
|
36901
36965
|
}
|
|
36902
36966
|
return false;
|
|
36903
36967
|
}
|
|
36904
|
-
function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachableLines, tainted, code, language) {
|
|
36968
|
+
function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachableLines, tainted, code, language, types) {
|
|
36905
36969
|
const flows = [];
|
|
36906
36970
|
const sourcesWithVar = sources.filter(
|
|
36907
36971
|
(s) => typeof s.variable === "string" && s.variable.length > 0
|
|
@@ -37158,12 +37222,32 @@ function detectExpressionScanFlows(calls, sources, sinks, sanitizers, unreachabl
|
|
|
37158
37222
|
for (const s of sourcesWithVar) {
|
|
37159
37223
|
if (s.line < anchor.line) anchor = s;
|
|
37160
37224
|
}
|
|
37225
|
+
const methodAt = (line) => {
|
|
37226
|
+
for (const t of types ?? []) {
|
|
37227
|
+
for (const m of t.methods) {
|
|
37228
|
+
if (line >= m.start_line && line <= m.end_line) return m.name;
|
|
37229
|
+
}
|
|
37230
|
+
}
|
|
37231
|
+
return null;
|
|
37232
|
+
};
|
|
37161
37233
|
const existingVars = new Set(sourcesWithVar.map((s) => s.variable));
|
|
37162
|
-
for (const [varName] of derived) {
|
|
37234
|
+
for (const [varName, derivedLine] of derived) {
|
|
37163
37235
|
if (!varName || existingVars.has(varName)) continue;
|
|
37236
|
+
const owner = methodAt(derivedLine);
|
|
37237
|
+
let scopedAnchor = anchor;
|
|
37238
|
+
if (owner) {
|
|
37239
|
+
let best;
|
|
37240
|
+
for (const s of sourcesWithVar) {
|
|
37241
|
+
const sOwner = s.in_method ?? methodAt(s.line);
|
|
37242
|
+
if (sOwner !== owner) continue;
|
|
37243
|
+
if (!best || s.line < best.line) best = s;
|
|
37244
|
+
}
|
|
37245
|
+
if (best) scopedAnchor = best;
|
|
37246
|
+
}
|
|
37164
37247
|
sourcesWithVar.push({
|
|
37165
|
-
...
|
|
37166
|
-
variable: varName
|
|
37248
|
+
...scopedAnchor,
|
|
37249
|
+
variable: varName,
|
|
37250
|
+
...owner ? { in_method: owner } : {}
|
|
37167
37251
|
});
|
|
37168
37252
|
existingVars.add(varName);
|
|
37169
37253
|
}
|
|
@@ -14356,14 +14356,30 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
14356
14356
|
// regex registry so it's recognized in subscript/var contexts.
|
|
14357
14357
|
{ pattern: /\binput\s*\(/, sourceType: "io_input" }
|
|
14358
14358
|
];
|
|
14359
|
+
function dropCSharpObjectCarriedWaypoints(sinks, calls) {
|
|
14360
|
+
const zeroArgCtors = /* @__PURE__ */ new Set();
|
|
14361
|
+
for (const call of calls) {
|
|
14362
|
+
if (call.is_constructor && call.arguments.length === 0) {
|
|
14363
|
+
zeroArgCtors.add(`${call.location.line}:${call.method_name}`);
|
|
14364
|
+
}
|
|
14365
|
+
}
|
|
14366
|
+
return sinks.filter((sink) => {
|
|
14367
|
+
if (sink.type !== "sql_injection") return true;
|
|
14368
|
+
if (sink.method && zeroArgCtors.has(`${sink.line}:${sink.method}`)) {
|
|
14369
|
+
return false;
|
|
14370
|
+
}
|
|
14371
|
+
return true;
|
|
14372
|
+
});
|
|
14373
|
+
}
|
|
14359
14374
|
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language, code) {
|
|
14360
14375
|
const sourceLines = code !== void 0 ? code.split("\n") : void 0;
|
|
14361
14376
|
const sources = findSources(calls, types, config.sources, sourceLines, language);
|
|
14362
14377
|
let sinkPatterns = expandPromisifyAliases(config.sinks, sourceLines, language);
|
|
14363
14378
|
sinkPatterns = expandIndirectEvalAliases(sinkPatterns, sourceLines, language);
|
|
14364
14379
|
const sinks = findSinks(calls, sinkPatterns, typeHierarchy, language, sourceLines, types);
|
|
14380
|
+
const gatedSinks = language === "csharp" ? dropCSharpObjectCarriedWaypoints(sinks, calls) : sinks;
|
|
14365
14381
|
const sanitizers = findSanitizers(calls, types, config.sanitizers, sourceLines);
|
|
14366
|
-
return { sources, sinks, sanitizers };
|
|
14382
|
+
return { sources, sinks: gatedSinks, sanitizers };
|
|
14367
14383
|
}
|
|
14368
14384
|
function sinkPatternAppliesTo(pattern, language) {
|
|
14369
14385
|
if (language === void 0) return true;
|
|
@@ -14634,7 +14650,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
14634
14650
|
}
|
|
14635
14651
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
14636
14652
|
for (const source of sources) {
|
|
14637
|
-
const key = `${source.line}:${source.type}`;
|
|
14653
|
+
const key = source.type === "interprocedural_param" && source.variable ? `${source.line}:${source.type}:${source.variable}` : `${source.line}:${source.type}`;
|
|
14638
14654
|
const existing = sourceMap.get(key);
|
|
14639
14655
|
if (!existing || source.confidence > existing.confidence) {
|
|
14640
14656
|
sourceMap.set(key, source);
|
|
@@ -15252,6 +15268,15 @@ var CWE_78_RECEIVER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
|
15252
15268
|
// hutool
|
|
15253
15269
|
"RuntimeUtil"
|
|
15254
15270
|
]);
|
|
15271
|
+
function isRegexReceiver(receiver, sourceLines) {
|
|
15272
|
+
const r = (receiver ?? "").trim();
|
|
15273
|
+
if (r.length === 0) return false;
|
|
15274
|
+
if (r.startsWith("/") && /\/[a-z]*$/.test(r)) return true;
|
|
15275
|
+
if (/^(?:new\s+)?RegExp\s*\(/.test(r)) return true;
|
|
15276
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(r) || !sourceLines) return false;
|
|
15277
|
+
const decl = new RegExp(`(?:const|let|var)\\s+${escapeRe(r)}\\s*=\\s*(?:/|(?:new\\s+)?RegExp\\s*\\()`);
|
|
15278
|
+
return sourceLines.some((l) => decl.test(l));
|
|
15279
|
+
}
|
|
15255
15280
|
function isFunctionCallbackArgument(arg) {
|
|
15256
15281
|
if (arg.literal !== null && arg.literal !== void 0) return false;
|
|
15257
15282
|
const expr = (arg.expression ?? "").trim();
|
|
@@ -15434,6 +15459,12 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
|
|
|
15434
15459
|
continue;
|
|
15435
15460
|
}
|
|
15436
15461
|
}
|
|
15462
|
+
if (pattern.type === "command_injection" && call.method_name === "exec" && (language === "javascript" || language === "typescript") && isRegexReceiver(call.receiver, sourceLines)) {
|
|
15463
|
+
continue;
|
|
15464
|
+
}
|
|
15465
|
+
if (pattern.type === "code_injection" && language === "python" && call.method_name === "compile" && call.receiver && call.receiver !== "builtins") {
|
|
15466
|
+
continue;
|
|
15467
|
+
}
|
|
15437
15468
|
if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
|
|
15438
15469
|
continue;
|
|
15439
15470
|
}
|
|
@@ -16749,6 +16780,9 @@ function findInitialTaint(sources, callsByLine, defsByLine) {
|
|
|
16749
16780
|
for (const source of sources) {
|
|
16750
16781
|
const defsOnLine = defsByLine.get(source.line) ?? [];
|
|
16751
16782
|
for (const def of defsOnLine) {
|
|
16783
|
+
if (source.type === "interprocedural_param" && source.variable && def.kind === "param" && def.variable !== source.variable) {
|
|
16784
|
+
continue;
|
|
16785
|
+
}
|
|
16752
16786
|
tainted.push({
|
|
16753
16787
|
variable: def.variable,
|
|
16754
16788
|
defId: def.id,
|
|
@@ -14290,14 +14290,30 @@ var PYTHON_TAINTED_PATTERNS = [
|
|
|
14290
14290
|
// regex registry so it's recognized in subscript/var contexts.
|
|
14291
14291
|
{ pattern: /\binput\s*\(/, sourceType: "io_input" }
|
|
14292
14292
|
];
|
|
14293
|
+
function dropCSharpObjectCarriedWaypoints(sinks, calls) {
|
|
14294
|
+
const zeroArgCtors = /* @__PURE__ */ new Set();
|
|
14295
|
+
for (const call of calls) {
|
|
14296
|
+
if (call.is_constructor && call.arguments.length === 0) {
|
|
14297
|
+
zeroArgCtors.add(`${call.location.line}:${call.method_name}`);
|
|
14298
|
+
}
|
|
14299
|
+
}
|
|
14300
|
+
return sinks.filter((sink) => {
|
|
14301
|
+
if (sink.type !== "sql_injection") return true;
|
|
14302
|
+
if (sink.method && zeroArgCtors.has(`${sink.line}:${sink.method}`)) {
|
|
14303
|
+
return false;
|
|
14304
|
+
}
|
|
14305
|
+
return true;
|
|
14306
|
+
});
|
|
14307
|
+
}
|
|
14293
14308
|
function analyzeTaint(calls, types, config = getDefaultConfig(), typeHierarchy, language, code) {
|
|
14294
14309
|
const sourceLines = code !== void 0 ? code.split("\n") : void 0;
|
|
14295
14310
|
const sources = findSources(calls, types, config.sources, sourceLines, language);
|
|
14296
14311
|
let sinkPatterns = expandPromisifyAliases(config.sinks, sourceLines, language);
|
|
14297
14312
|
sinkPatterns = expandIndirectEvalAliases(sinkPatterns, sourceLines, language);
|
|
14298
14313
|
const sinks = findSinks(calls, sinkPatterns, typeHierarchy, language, sourceLines, types);
|
|
14314
|
+
const gatedSinks = language === "csharp" ? dropCSharpObjectCarriedWaypoints(sinks, calls) : sinks;
|
|
14299
14315
|
const sanitizers = findSanitizers(calls, types, config.sanitizers, sourceLines);
|
|
14300
|
-
return { sources, sinks, sanitizers };
|
|
14316
|
+
return { sources, sinks: gatedSinks, sanitizers };
|
|
14301
14317
|
}
|
|
14302
14318
|
function sinkPatternAppliesTo(pattern, language) {
|
|
14303
14319
|
if (language === void 0) return true;
|
|
@@ -14568,7 +14584,7 @@ function findSources(calls, types, patterns, sourceLines, language) {
|
|
|
14568
14584
|
}
|
|
14569
14585
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
14570
14586
|
for (const source of sources) {
|
|
14571
|
-
const key = `${source.line}:${source.type}`;
|
|
14587
|
+
const key = source.type === "interprocedural_param" && source.variable ? `${source.line}:${source.type}:${source.variable}` : `${source.line}:${source.type}`;
|
|
14572
14588
|
const existing = sourceMap.get(key);
|
|
14573
14589
|
if (!existing || source.confidence > existing.confidence) {
|
|
14574
14590
|
sourceMap.set(key, source);
|
|
@@ -15186,6 +15202,15 @@ var CWE_78_RECEIVER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
|
15186
15202
|
// hutool
|
|
15187
15203
|
"RuntimeUtil"
|
|
15188
15204
|
]);
|
|
15205
|
+
function isRegexReceiver(receiver, sourceLines) {
|
|
15206
|
+
const r = (receiver ?? "").trim();
|
|
15207
|
+
if (r.length === 0) return false;
|
|
15208
|
+
if (r.startsWith("/") && /\/[a-z]*$/.test(r)) return true;
|
|
15209
|
+
if (/^(?:new\s+)?RegExp\s*\(/.test(r)) return true;
|
|
15210
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(r) || !sourceLines) return false;
|
|
15211
|
+
const decl = new RegExp(`(?:const|let|var)\\s+${escapeRe(r)}\\s*=\\s*(?:/|(?:new\\s+)?RegExp\\s*\\()`);
|
|
15212
|
+
return sourceLines.some((l) => decl.test(l));
|
|
15213
|
+
}
|
|
15189
15214
|
function isFunctionCallbackArgument(arg) {
|
|
15190
15215
|
if (arg.literal !== null && arg.literal !== void 0) return false;
|
|
15191
15216
|
const expr = (arg.expression ?? "").trim();
|
|
@@ -15368,6 +15393,12 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
|
|
|
15368
15393
|
continue;
|
|
15369
15394
|
}
|
|
15370
15395
|
}
|
|
15396
|
+
if (pattern.type === "command_injection" && call.method_name === "exec" && (language === "javascript" || language === "typescript") && isRegexReceiver(call.receiver, sourceLines)) {
|
|
15397
|
+
continue;
|
|
15398
|
+
}
|
|
15399
|
+
if (pattern.type === "code_injection" && language === "python" && call.method_name === "compile" && call.receiver && call.receiver !== "builtins") {
|
|
15400
|
+
continue;
|
|
15401
|
+
}
|
|
15371
15402
|
if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
|
|
15372
15403
|
continue;
|
|
15373
15404
|
}
|
|
@@ -16683,6 +16714,9 @@ function findInitialTaint(sources, callsByLine, defsByLine) {
|
|
|
16683
16714
|
for (const source of sources) {
|
|
16684
16715
|
const defsOnLine = defsByLine.get(source.line) ?? [];
|
|
16685
16716
|
for (const def of defsOnLine) {
|
|
16717
|
+
if (source.type === "interprocedural_param" && source.variable && def.kind === "param" && def.variable !== source.variable) {
|
|
16718
|
+
continue;
|
|
16719
|
+
}
|
|
16686
16720
|
tainted.push({
|
|
16687
16721
|
variable: def.variable,
|
|
16688
16722
|
defId: def.id,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circle-ir",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.11",
|
|
4
4
|
"description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|