circle-ir 4.9.25 → 4.9.26
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/language-sources-pass.d.ts.map +1 -1
- package/dist/analysis/passes/language-sources-pass.js +143 -10
- package/dist/analysis/passes/language-sources-pass.js.map +1 -1
- package/dist/analysis/passes/taint-propagation-pass.js +29 -0
- package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
- package/dist/browser/circle-ir.js +106 -3
- package/dist/core/circle-ir-core.cjs +2 -1
- package/dist/core/circle-ir-core.js +2 -1
- package/dist/core/parser.d.ts.map +1 -1
- package/dist/core/parser.js +5 -2
- package/dist/core/parser.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAwB,WAAW,EAAO,MAAM,sBAAsB,CAAC;AAC3H,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAyB9E,eAAO,MAAM,mBAAmB;;UACK,YAAY;;;UAEb,WAAW;;;UACR,aAAa;;;UACb,aAAa;;;UACjB,WAAW;;;UAGR,YAAY;;;UAQX,WAAW;;;UACV,UAAU;;;UAIC,WAAW;IA8D7D,CAAC;AAwDF,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,eAAe,EAAE,SAAS,EAAE,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,EAAE,cAAc,EAAE,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAMD,qBAAa,mBAAoB,YAAW,YAAY,CAAC,qBAAqB,CAAC;IAC7E,QAAQ,CAAC,IAAI,sBAAsB;IACnC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,qBAAqB,CAogB3C;CACF;
|
|
1
|
+
{"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"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"}
|
|
@@ -1458,6 +1458,66 @@ function findGoRequestBodySources(sourceCode, language) {
|
|
|
1458
1458
|
continue;
|
|
1459
1459
|
}
|
|
1460
1460
|
}
|
|
1461
|
+
// `sc := bufio.NewScanner(r.Body)` / `br := bufio.NewReader(r.Body)` — the
|
|
1462
|
+
// wrapper itself is not the data; its reads are. Each `sc.Text()` /
|
|
1463
|
+
// `sc.Bytes()` / `br.ReadString(…)` / `br.ReadBytes(…)` / `br.ReadLine()`
|
|
1464
|
+
// inside the same function body is an http_body source. Scoped to the
|
|
1465
|
+
// wrapper variable's own block, so an unrelated `sc` elsewhere in the file
|
|
1466
|
+
// (e.g. a scanner over os.Stdin) is never seeded.
|
|
1467
|
+
const wrapRe = new RegExp(`^\\s*(?:var\\s+)?([A-Za-z_]\\w*)\\s*:?=\\s*bufio\\s*\\.\\s*New(?:Scanner|Reader|ReaderSize)\\s*\\(.*${bodyRef}`);
|
|
1468
|
+
const braceDelta = (s) => {
|
|
1469
|
+
// Ignore braces inside string/rune literals and trailing comments.
|
|
1470
|
+
const code = s.replace(/"(?:[^"\\]|\\.)*"|`[^`]*`|'(?:[^'\\]|\\.)*'/g, '""').replace(/\/\/.*$/, '');
|
|
1471
|
+
let d = 0;
|
|
1472
|
+
for (const ch of code) {
|
|
1473
|
+
if (ch === '{')
|
|
1474
|
+
d++;
|
|
1475
|
+
else if (ch === '}')
|
|
1476
|
+
d--;
|
|
1477
|
+
}
|
|
1478
|
+
return d;
|
|
1479
|
+
};
|
|
1480
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1481
|
+
const w = wrapRe.exec(lines[i]);
|
|
1482
|
+
if (!w)
|
|
1483
|
+
continue;
|
|
1484
|
+
const wrapper = w[1];
|
|
1485
|
+
if (wrapper === '_')
|
|
1486
|
+
continue;
|
|
1487
|
+
const readRe = new RegExp(`(?<![\\w.])${wrapper}\\s*\\.\\s*(Text|Bytes|ReadString|ReadBytes|ReadLine|ReadSlice)\\s*\\(`);
|
|
1488
|
+
const assignRe = new RegExp(`^\\s*(?:var\\s+)?([A-Za-z_][\\w\\s,]*?)\\s*:?=(?!=)\\s*(?:string\\s*\\(\\s*)?${wrapper}\\s*\\.\\s*(?:Text|Bytes|ReadString|ReadBytes|ReadLine|ReadSlice)\\s*\\(`);
|
|
1489
|
+
const rebindRe = new RegExp(`(?<![\\w.])${wrapper}\\s*:?=(?!=)`);
|
|
1490
|
+
// Walk forward until the block holding the declaration closes.
|
|
1491
|
+
let depth = 0;
|
|
1492
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
1493
|
+
depth += braceDelta(lines[j - 1]);
|
|
1494
|
+
if (depth < 0)
|
|
1495
|
+
break;
|
|
1496
|
+
const line = lines[j];
|
|
1497
|
+
if (/^\s*\/\//.test(line))
|
|
1498
|
+
continue;
|
|
1499
|
+
if (rebindRe.test(line))
|
|
1500
|
+
break; // wrapper re-bound to something else
|
|
1501
|
+
const rd = readRe.exec(line);
|
|
1502
|
+
if (!rd)
|
|
1503
|
+
continue;
|
|
1504
|
+
// `line := sc.Text()` binds the LHS. A read used inline as a call
|
|
1505
|
+
// argument (`db.Query("…" + sc.Text())`) gets the `<inline>` marker
|
|
1506
|
+
// (as #339 does for C#): it matches no real name, so only a sink on
|
|
1507
|
+
// this very line is reached. Leaving it with NO variable made
|
|
1508
|
+
// findInitialTaint seed every def on the FOLLOWING line by adjacency,
|
|
1509
|
+
// so `log.Println(sc.Text())` tainted a constant `x := "fixed"`.
|
|
1510
|
+
const as = assignRe.exec(line);
|
|
1511
|
+
let variable = '<inline>';
|
|
1512
|
+
if (as) {
|
|
1513
|
+
const bound = as[1].split(',').map((v) => v.trim()).find((v) => v !== '_' && v !== 'err' && /^[A-Za-z_]\w*$/.test(v));
|
|
1514
|
+
if (!bound)
|
|
1515
|
+
continue;
|
|
1516
|
+
variable = bound;
|
|
1517
|
+
}
|
|
1518
|
+
push(variable, j + 1, `bufio ${wrapper}.${rd[1]}() over req.Body`);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1461
1521
|
return sources;
|
|
1462
1522
|
}
|
|
1463
1523
|
function findCSharpRequestSources(sourceCode, language) {
|
|
@@ -1511,20 +1571,93 @@ function findCSharpRequestSources(sourceCode, language) {
|
|
|
1511
1571
|
const formFileReadRe = formFileParams.size > 0
|
|
1512
1572
|
? new RegExp(`\\b(?:${[...formFileParams].join('|')})\\s*\\.\\s*(?:FileName|ContentType)\\b`)
|
|
1513
1573
|
: null;
|
|
1574
|
+
const classify = (text) => requestReadRe.test(text)
|
|
1575
|
+
? 'http_param'
|
|
1576
|
+
: formFileReadRe?.test(text)
|
|
1577
|
+
? 'http_param'
|
|
1578
|
+
: consoleReadRe.test(text)
|
|
1579
|
+
? 'io_input'
|
|
1580
|
+
: envReadRe.test(text)
|
|
1581
|
+
? 'env_input'
|
|
1582
|
+
: null;
|
|
1583
|
+
// cognium-dev#339 — a bare expression statement reads the request INLINE in
|
|
1584
|
+
// the call, with no local to bind:
|
|
1585
|
+
//
|
|
1586
|
+
// var s = File.Create(Path.Combine("/uploads", file.FileName)); // bound (LHS `s`)
|
|
1587
|
+
// File.Create(Path.Combine("/uploads", file.FileName)); // was NOT
|
|
1588
|
+
//
|
|
1589
|
+
// Java/Python/JS already seed such inline reads as call-anchored sources on
|
|
1590
|
+
// the statement line, which the taint pass's inline-colocation step pairs
|
|
1591
|
+
// with a sink on that same line. Mirror that shape here: a source anchored
|
|
1592
|
+
// on the statement (see `variable` below). Scoped to a single-line statement
|
|
1593
|
+
// that opens with a call (`Recv.M(` / `M(`), so a declaration, `return`,
|
|
1594
|
+
// control-flow header or a multi-line fragment is never seeded this way.
|
|
1595
|
+
//
|
|
1596
|
+
// The read must sit INSIDE the statement's argument list. A read that is
|
|
1597
|
+
// the statement's own callee or receiver — `Console.ReadLine();` (value
|
|
1598
|
+
// discarded), `Request.Body.CopyToAsync(ms);` — is not passed to anything
|
|
1599
|
+
// on this line, so there is nothing for it to reach here.
|
|
1600
|
+
const inlineReads = [
|
|
1601
|
+
[requestReadRe, 'http_param'],
|
|
1602
|
+
[formFileReadRe, 'http_param'],
|
|
1603
|
+
[consoleReadRe, 'io_input'],
|
|
1604
|
+
[envReadRe, 'env_input'],
|
|
1605
|
+
];
|
|
1606
|
+
const inlineRead = (text) => {
|
|
1607
|
+
const argsStart = text.indexOf('(');
|
|
1608
|
+
for (const [re, type] of inlineReads) {
|
|
1609
|
+
if (!re)
|
|
1610
|
+
continue;
|
|
1611
|
+
const g = new RegExp(re.source, 'g');
|
|
1612
|
+
let hit;
|
|
1613
|
+
while ((hit = g.exec(text)) !== null) {
|
|
1614
|
+
if (hit.index > argsStart) {
|
|
1615
|
+
return { type, read: hit[0].replace(/\s+/g, '').replace(/[([]$/, '') };
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
return null;
|
|
1620
|
+
};
|
|
1621
|
+
const exprStmtCallRe = /^\s*(?:await\s+)?[A-Za-z_][\w.]*(?:<[^>]*>)?\s*\(.*\)\s*;\s*$/;
|
|
1622
|
+
const nonCallKeywordRe = /^\s*(?:await\s+)?(?:if|while|for|foreach|switch|using|lock|return|throw|catch|when|nameof|typeof|sizeof|default)\b/;
|
|
1514
1623
|
for (let i = 0; i < lines.length; i++) {
|
|
1515
1624
|
const m = assignRe.exec(lines[i]);
|
|
1516
|
-
if (!m)
|
|
1625
|
+
if (!m) {
|
|
1626
|
+
const stmt = lines[i];
|
|
1627
|
+
if (!exprStmtCallRe.test(stmt) || nonCallKeywordRe.test(stmt))
|
|
1628
|
+
continue;
|
|
1629
|
+
const hit = inlineRead(stmt);
|
|
1630
|
+
if (!hit)
|
|
1631
|
+
continue;
|
|
1632
|
+
const { type, read } = hit;
|
|
1633
|
+
const lineNumber = i + 1;
|
|
1634
|
+
if (sources.some(s => s.line === lineNumber))
|
|
1635
|
+
continue;
|
|
1636
|
+
// `variable` is the `<inline>` marker (the same one the inline
|
|
1637
|
+
// colocation flow puts on its path steps), never a real name. It
|
|
1638
|
+
// must be set, and must match nothing:
|
|
1639
|
+
// - with NO variable, `findInitialTaint` seeds every def on the
|
|
1640
|
+
// FOLLOWING line by adjacency, so `Log(file.FileName);` followed by
|
|
1641
|
+
// `var x = "/tmp/a";` tainted the constant `x`;
|
|
1642
|
+
// - with the read text itself (`file.FileName`) as the variable, the
|
|
1643
|
+
// colocation path treats it as an LHS binding and hands the pair
|
|
1644
|
+
// to the variable scan, which only looks at strictly later sinks —
|
|
1645
|
+
// so the same-line flow this exists for was lost.
|
|
1646
|
+
// The marker reaches only a sink on this very statement.
|
|
1647
|
+
const code = stmt.trim();
|
|
1648
|
+
sources.push({
|
|
1649
|
+
type,
|
|
1650
|
+
location: `${read} in ${code.substring(0, 50)}${code.length > 50 ? '...' : ''}`,
|
|
1651
|
+
severity: 'high',
|
|
1652
|
+
line: lineNumber,
|
|
1653
|
+
confidence: 1.0,
|
|
1654
|
+
variable: '<inline>',
|
|
1655
|
+
code,
|
|
1656
|
+
});
|
|
1517
1657
|
continue;
|
|
1658
|
+
}
|
|
1518
1659
|
const [, varName, rhs] = m;
|
|
1519
|
-
const type =
|
|
1520
|
-
? 'http_param'
|
|
1521
|
-
: formFileReadRe?.test(rhs)
|
|
1522
|
-
? 'http_param'
|
|
1523
|
-
: consoleReadRe.test(rhs)
|
|
1524
|
-
? 'io_input'
|
|
1525
|
-
: envReadRe.test(rhs)
|
|
1526
|
-
? 'env_input'
|
|
1527
|
-
: null;
|
|
1660
|
+
const type = classify(rhs);
|
|
1528
1661
|
if (!type)
|
|
1529
1662
|
continue;
|
|
1530
1663
|
const lineNumber = i + 1;
|