circle-ir 3.48.0 → 3.49.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.
Files changed (34) hide show
  1. package/dist/analysis/config-loader.d.ts.map +1 -1
  2. package/dist/analysis/config-loader.js +86 -2
  3. package/dist/analysis/config-loader.js.map +1 -1
  4. package/dist/analysis/constant-propagation/index.d.ts.map +1 -1
  5. package/dist/analysis/constant-propagation/index.js +16 -6
  6. package/dist/analysis/constant-propagation/index.js.map +1 -1
  7. package/dist/analysis/passes/insecure-cookie-pass.d.ts +53 -0
  8. package/dist/analysis/passes/insecure-cookie-pass.d.ts.map +1 -0
  9. package/dist/analysis/passes/insecure-cookie-pass.js +109 -0
  10. package/dist/analysis/passes/insecure-cookie-pass.js.map +1 -0
  11. package/dist/analysis/passes/interprocedural-pass.d.ts.map +1 -1
  12. package/dist/analysis/passes/interprocedural-pass.js +7 -0
  13. package/dist/analysis/passes/interprocedural-pass.js.map +1 -1
  14. package/dist/analysis/passes/language-sources-pass.d.ts +14 -0
  15. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  16. package/dist/analysis/passes/language-sources-pass.js +50 -0
  17. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  18. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  19. package/dist/analysis/passes/sink-filter-pass.js +21 -2
  20. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  21. package/dist/analysis/passes/taint-propagation-pass.js +94 -3
  22. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  23. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  24. package/dist/analysis/taint-matcher.js +117 -20
  25. package/dist/analysis/taint-matcher.js.map +1 -1
  26. package/dist/analyzer.d.ts.map +1 -1
  27. package/dist/analyzer.js +3 -0
  28. package/dist/analyzer.js.map +1 -1
  29. package/dist/browser/circle-ir.js +356 -26
  30. package/dist/core/circle-ir-core.cjs +189 -23
  31. package/dist/core/circle-ir-core.js +189 -23
  32. package/dist/core/extractors/types.js +85 -2
  33. package/dist/core/extractors/types.js.map +1 -1
  34. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA4a1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA4sCtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EA6LhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA4a1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA4xCtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAoMhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
@@ -1229,6 +1229,26 @@ export const DEFAULT_SINKS = [
1229
1229
  { method: 'setQuotedArgumentsEnabled', class: 'Shell', type: 'command_injection', cwe: 'CWE-78', severity: 'high', arg_positions: [0] },
1230
1230
  // Sandbox/script security
1231
1231
  { method: 'onNewInstance', class: 'SandboxInterceptor', type: 'command_injection', cwe: 'CWE-78', severity: 'critical', arg_positions: [0] },
1232
+ // Java Log Injection (slf4j / logback / java.util.logging) — CWE-117
1233
+ // Issue #44: log.info/warn/error/debug emit the message argument and any
1234
+ // {} format arguments to the log stream. Untrusted input forwarded into
1235
+ // these calls allows log forging (newline injection) and downstream log
1236
+ // analyzer pollution. Scoped to `java` so the generic method names don't
1237
+ // collide with JS console / Python logger entries below.
1238
+ { method: 'info', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['java'] },
1239
+ { method: 'warn', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['java'] },
1240
+ { method: 'error', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['java'] },
1241
+ { method: 'debug', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['java'] },
1242
+ { method: 'trace', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['java'] },
1243
+ // java.util.logging.Logger uses the same class name `Logger` — same entries above cover it.
1244
+ // Severity-tagged levels: SEVERE/WARNING/INFO/CONFIG/FINE/FINER/FINEST
1245
+ { method: 'severe', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1246
+ { method: 'warning', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1247
+ { method: 'config', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1248
+ { method: 'fine', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1249
+ { method: 'finer', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1250
+ { method: 'finest', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0], languages: ['java'] },
1251
+ { method: 'log', class: 'Logger', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [1, 2, 3], languages: ['java'] },
1232
1252
  // =========================================================================
1233
1253
  // Node.js/Express Sinks
1234
1254
  // =========================================================================
@@ -1281,13 +1301,47 @@ export const DEFAULT_SINKS = [
1281
1301
  { method: 'runInContext', class: 'vm', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
1282
1302
  { method: 'runInNewContext', class: 'vm', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
1283
1303
  { method: 'runInThisContext', class: 'vm', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0] },
1284
- // Node.js NoSQL Injection (MongoDB)
1304
+ // Node.js NoSQL Injection (MongoDB native driver + mongoose) — CWE-943
1305
+ // Issue #45: the bare `class: 'Collection'` constraint missed mongoose's
1306
+ // fluent chains (mongoose.connection.db.collection('x').find({...})) and
1307
+ // Model.find calls because the call-site receiver type does not resolve
1308
+ // to `Collection`. Add classless+language-scoped entries for the
1309
+ // MongoDB-specific method names (findOne/aggregate/updateOne/etc.) and
1310
+ // mongoose `Model`/`Query` class entries. Bare `find` stays class-scoped
1311
+ // to avoid colliding with Array.prototype.find.
1285
1312
  { method: 'find', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1286
1313
  { method: 'findOne', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1287
1314
  { method: 'updateOne', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1288
1315
  { method: 'updateMany', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1289
1316
  { method: 'deleteOne', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1290
1317
  { method: 'deleteMany', class: 'Collection', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0] },
1318
+ // Mongoose Model/Query class entries — Model.find/findOne/etc.
1319
+ { method: 'find', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1320
+ { method: 'findOne', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1321
+ { method: 'findById', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1322
+ { method: 'findOneAndUpdate', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1323
+ { method: 'findOneAndDelete', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1324
+ { method: 'findOneAndReplace', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1325
+ { method: 'updateOne', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1326
+ { method: 'updateMany', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1327
+ { method: 'deleteOne', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1328
+ { method: 'deleteMany', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1329
+ { method: 'countDocuments', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1330
+ { method: 'aggregate', class: 'Model', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1331
+ // Mongoose Query class entries — chain methods returning Query
1332
+ { method: 'where', class: 'Query', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1333
+ { method: 'equals', class: 'Query', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1334
+ // Classless MongoDB-specific method names (rare outside MongoDB APIs) —
1335
+ // language-scoped to JS/TS. Excludes plain `find` (Array.prototype.find FP).
1336
+ { method: 'findOne', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1337
+ { method: 'findOneAndUpdate', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1338
+ { method: 'findOneAndDelete', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1339
+ { method: 'findOneAndReplace', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1340
+ { method: 'updateOne', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1341
+ { method: 'updateMany', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0, 1], languages: ['javascript', 'typescript'] },
1342
+ { method: 'deleteOne', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1343
+ { method: 'deleteMany', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1344
+ { method: 'aggregate', type: 'nosql_injection', cwe: 'CWE-943', severity: 'high', arg_positions: [0], languages: ['javascript', 'typescript'] },
1291
1345
  // Node.js SSRF (HTTP clients)
1292
1346
  { method: 'get', class: 'axios', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
1293
1347
  { method: 'post', class: 'axios', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
@@ -1309,6 +1363,24 @@ export const DEFAULT_SINKS = [
1309
1363
  { method: 'post', class: 'superagent', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
1310
1364
  // node-fetch
1311
1365
  { method: 'default', class: 'node-fetch', type: 'ssrf', cwe: 'CWE-918', severity: 'high', arg_positions: [0] },
1366
+ // Node.js / JavaScript Log Injection (console.*) — CWE-117
1367
+ // Issue #44: console.log/warn/error/info with tainted template literals
1368
+ // allow log forging (newline-injection) and downstream log analyzer
1369
+ // pollution. Scoped to JS/TS so the bare class `console` doesn't collide
1370
+ // with Python `console` module or Java identifiers.
1371
+ { method: 'log', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1372
+ { method: 'warn', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1373
+ { method: 'error', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1374
+ { method: 'info', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1375
+ { method: 'debug', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1376
+ { method: 'trace', class: 'console', type: 'log_injection', cwe: 'CWE-117', severity: 'low', arg_positions: [0, 1, 2, 3], languages: ['javascript', 'typescript'] },
1377
+ // Node.js / Express Open Redirect — CWE-601
1378
+ // Issue #46: `res.redirect(req.query.next)` did not fire because the
1379
+ // legacy `class: 'Response'` constraint depended on receiver type
1380
+ // resolution of the Express `res` parameter. Mirror Python's classless
1381
+ // pattern with a language-scoped classless entry. The method name
1382
+ // `redirect` is rare outside HTTP frameworks so the FP risk is low.
1383
+ { method: 'redirect', type: 'open_redirect', cwe: 'CWE-601', severity: 'medium', arg_positions: [0], languages: ['javascript', 'typescript'] },
1312
1384
  // =========================================================================
1313
1385
  // Python Sinks
1314
1386
  // =========================================================================
@@ -1350,7 +1422,12 @@ export const DEFAULT_SINKS = [
1350
1422
  { method: 'rmtree', class: 'shutil', type: 'path_traversal', cwe: 'CWE-22', severity: 'critical', arg_positions: [0] },
1351
1423
  { method: 'send_file', type: 'path_traversal', cwe: 'CWE-22', severity: 'high', arg_positions: [0], languages: ['python'] },
1352
1424
  // Python XSS / SSTI
1353
- { method: 'render_template_string', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
1425
+ // Issue #54: Flask's `render_template_string(template_str)` with an
1426
+ // attacker-controlled template string is Server-Side Template Injection
1427
+ // (Jinja2 SSTI → RCE), not reflected XSS. Classify as code_injection
1428
+ // (CWE-94) with critical severity to match `jinja2.Template().render()`
1429
+ // and `Template.from_string()` entries above.
1430
+ { method: 'render_template_string', type: 'code_injection', cwe: 'CWE-94', severity: 'critical', arg_positions: [0], languages: ['python'] },
1354
1431
  { method: 'Markup', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
1355
1432
  { method: 'mark_safe', type: 'xss', cwe: 'CWE-79', severity: 'high', arg_positions: [0], languages: ['python'] },
1356
1433
  // Python SSRF
@@ -1703,6 +1780,13 @@ export const DEFAULT_SANITIZERS = [
1703
1780
  { method: 'secure_filename', class: 'werkzeug.utils', removes: ['path_traversal'] },
1704
1781
  { method: 'basename', class: 'os.path', removes: ['path_traversal'] },
1705
1782
  { method: 'normpath', class: 'os.path', removes: ['path_traversal'] },
1783
+ // Issue #48 part 2: realpath/abspath are canonical Python path-canonicalization
1784
+ // functions (analogous to Java File.getCanonicalPath). Register on both
1785
+ // `os.path` and the bare `path` receiver to cover `import os.path as path`.
1786
+ { method: 'realpath', class: 'os.path', removes: ['path_traversal'] },
1787
+ { method: 'abspath', class: 'os.path', removes: ['path_traversal'] },
1788
+ { method: 'realpath', class: 'path', removes: ['path_traversal'] },
1789
+ { method: 'abspath', class: 'path', removes: ['path_traversal'] },
1706
1790
  // Python Type coercion
1707
1791
  { method: 'int', removes: ['sql_injection', 'command_injection', 'xss'] },
1708
1792
  { method: 'float', removes: ['sql_injection', 'command_injection'] },