circle-ir 3.133.0 → 3.134.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.
@@ -360,4 +360,32 @@ export declare function findPythonInteractiveInterpreterCodeInjectionFindings(co
360
360
  * `web::Json<T>` / `HttpRequest` param, or `axum::body::Bytes`/`String` etc.
361
361
  */
362
362
  export declare function findRustEvalCrateCodeInjectionFindings(code: string, file: string): SastFinding[];
363
+ /**
364
+ * Sprint 84 detector A (#189) — Go MongoDB driver nosql_injection.
365
+ * The Go MongoDB driver call shape `coll.FindOne(ctx, bson.M{"k": <taint>})`
366
+ * (and siblings: Find / InsertOne / InsertMany / UpdateOne / UpdateMany /
367
+ * DeleteOne / DeleteMany / FindOneAndUpdate / FindOneAndDelete /
368
+ * FindOneAndReplace / Aggregate) is not modeled by configured sinks (those
369
+ * cover Node.js Mongo only). Fires when the filter argument (after `ctx`)
370
+ * references a value transitively derived from `*http.Request` extractors
371
+ * (URL.Query().Get / FormValue / PostFormValue / Header.Get / Cookie).
372
+ */
373
+ export declare function findGoMongoNosqlInjectionFindings(code: string, file: string): SastFinding[];
374
+ /**
375
+ * Sprint 84 detector B (#189) — Java Mongo driver nosql_injection.
376
+ * Mongo Java driver shape `users.find(eq("k", <taint>))` (and siblings)
377
+ * is not modeled by configured sinks (those cover Node.js Mongo only).
378
+ * Fires when the receiver call payload references a value transitively
379
+ * derived from servlet request extractors (request.getParameter /
380
+ * getHeader / getCookies / getReader / getQueryString / getPart).
381
+ */
382
+ export declare function findJavaMongoNosqlInjectionFindings(code: string, file: string): SastFinding[];
383
+ /**
384
+ * Sprint 84 detector C (#189) — Python mongoengine `$where` JS-string injection.
385
+ * The shape `User.objects(__raw__={'$where': "this.x == '" + n + "'"})`
386
+ * (and aliases via `$where` key with string concat / f-string) bypasses
387
+ * the configured nosql sinks. Fires when the `$where` value references
388
+ * a value transitively derived from Flask/Django/FastAPI request input.
389
+ */
390
+ export declare function findPythonMongoengineWhereNosqlInjectionFindings(code: string, file: string): SastFinding[];
363
391
  //# sourceMappingURL=language-sources-pass.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"language-sources-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/language-sources-pass.ts"],"names":[],"mappings":"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"}
@@ -223,6 +223,11 @@ export class LanguageSourcesPass {
223
223
  for (const finding of findGoPluginOpenCodeInjectionFindings(code, graph.ir.meta.file)) {
224
224
  ctx.addFinding(finding);
225
225
  }
226
+ // Sprint 84 (#189): Go nosql_injection — *mongo.Collection FindOne / Find
227
+ // / Insert / Update / Delete / Aggregate with bson.M{...tainted}.
228
+ for (const finding of findGoMongoNosqlInjectionFindings(code, graph.ir.meta.file)) {
229
+ ctx.addFinding(finding);
230
+ }
226
231
  }
227
232
  // -- Python: safe-handler sanitizer detectors (cognium-dev #114 Sprint 31) --
228
233
  if (language === 'python') {
@@ -261,6 +266,11 @@ export class LanguageSourcesPass {
261
266
  for (const finding of findPythonInteractiveInterpreterCodeInjectionFindings(code, graph.ir.meta.file)) {
262
267
  ctx.addFinding(finding);
263
268
  }
269
+ // Sprint 84 (#189): Python nosql_injection — mongoengine `__raw__={"$where":
270
+ // <tainted-string-concat>}` JS-string injection through MongoDB $where.
271
+ for (const finding of findPythonMongoengineWhereNosqlInjectionFindings(code, graph.ir.meta.file)) {
272
+ ctx.addFinding(finding);
273
+ }
264
274
  }
265
275
  // -- Rust: safe-handler sanitizer detectors (cognium-dev #115 Sprint 31) --
266
276
  if (language === 'rust') {
@@ -360,6 +370,11 @@ export class LanguageSourcesPass {
360
370
  for (const finding of findJavaResponseWriterXssFindings(code, graph.ir.meta.file)) {
361
371
  ctx.addFinding(finding);
362
372
  }
373
+ // Sprint 84 (#189): Java nosql_injection — MongoCollection find / insert /
374
+ // update / delete / aggregate with Filters.eq("k", <tainted servlet input>).
375
+ for (const finding of findJavaMongoNosqlInjectionFindings(code, graph.ir.meta.file)) {
376
+ ctx.addFinding(finding);
377
+ }
363
378
  }
364
379
  // Sprint 70 (#151): cross-language env-secret → external-network exfiltration.
365
380
  // Pattern findings only — no taint flow required (composed-flow shape that
@@ -5701,4 +5716,305 @@ export function findRustEvalCrateCodeInjectionFindings(code, file) {
5701
5716
  }
5702
5717
  return findings;
5703
5718
  }
5719
+ /**
5720
+ * Sprint 84 detector A (#189) — Go MongoDB driver nosql_injection.
5721
+ * The Go MongoDB driver call shape `coll.FindOne(ctx, bson.M{"k": <taint>})`
5722
+ * (and siblings: Find / InsertOne / InsertMany / UpdateOne / UpdateMany /
5723
+ * DeleteOne / DeleteMany / FindOneAndUpdate / FindOneAndDelete /
5724
+ * FindOneAndReplace / Aggregate) is not modeled by configured sinks (those
5725
+ * cover Node.js Mongo only). Fires when the filter argument (after `ctx`)
5726
+ * references a value transitively derived from `*http.Request` extractors
5727
+ * (URL.Query().Get / FormValue / PostFormValue / Header.Get / Cookie).
5728
+ */
5729
+ export function findGoMongoNosqlInjectionFindings(code, file) {
5730
+ const findings = [];
5731
+ if (typeof code !== 'string' || code.length === 0)
5732
+ return findings;
5733
+ // Gate: require some hint of the mongo-driver / bson namespace usage.
5734
+ if (!/(\bbson\s*\.\s*[MDAE]\b|mongo-driver|\*\s*mongo\.Collection)/.test(code)) {
5735
+ return findings;
5736
+ }
5737
+ const lines = code.split('\n');
5738
+ const reqExtractRe = /\b\w+\s*\.\s*(?:FormValue|PostFormValue|URL\s*\.\s*Query\s*\(\s*\)\s*\.\s*Get|Header\s*\.\s*Get|Cookie)\s*\(/;
5739
+ const httpReqParamRe = /\*\s*http\.Request\b/;
5740
+ const opsAlt = '(?:FindOne|Find|InsertOne|InsertMany|UpdateOne|UpdateMany|DeleteOne|DeleteMany|FindOneAndUpdate|FindOneAndDelete|FindOneAndReplace|Aggregate)';
5741
+ // Match call-site head only; balanced parens for args are extracted below.
5742
+ const callHeadRe = new RegExp(`\\.\\s*(${opsAlt})\\s*\\(`);
5743
+ function extractBalanced(line, openIdx) {
5744
+ let depth = 0;
5745
+ for (let k = openIdx; k < line.length; k++) {
5746
+ const ch = line[k];
5747
+ if (ch === '(')
5748
+ depth++;
5749
+ else if (ch === ')') {
5750
+ depth--;
5751
+ if (depth === 0)
5752
+ return line.substring(openIdx + 1, k);
5753
+ }
5754
+ }
5755
+ return null;
5756
+ }
5757
+ const funcs = [];
5758
+ let cur = null;
5759
+ for (let i = 0; i < lines.length; i++) {
5760
+ const t = lines[i].trim();
5761
+ if (/^func\b/.test(t)) {
5762
+ if (cur) {
5763
+ cur.end = i - 1;
5764
+ funcs.push(cur);
5765
+ }
5766
+ cur = { start: i, end: lines.length - 1 };
5767
+ }
5768
+ }
5769
+ if (cur)
5770
+ funcs.push(cur);
5771
+ for (const fn of funcs) {
5772
+ const header = lines[fn.start];
5773
+ if (!httpReqParamRe.test(header))
5774
+ continue;
5775
+ const taintedVars = new Set();
5776
+ for (let pass = 0; pass < 3; pass++) {
5777
+ const before = taintedVars.size;
5778
+ for (let i = fn.start; i <= fn.end; i++) {
5779
+ const trimmed = lines[i].trim();
5780
+ const assignMatch = trimmed.match(/^(\w+)\s*(?::=|=)\s*(.+?)(?:\s*\/\/.*)?$/);
5781
+ if (!assignMatch)
5782
+ continue;
5783
+ const lhs = assignMatch[1];
5784
+ const rhs = assignMatch[2];
5785
+ if (taintedVars.has(lhs))
5786
+ continue;
5787
+ if (reqExtractRe.test(rhs)) {
5788
+ taintedVars.add(lhs);
5789
+ continue;
5790
+ }
5791
+ for (const v of taintedVars) {
5792
+ if (new RegExp(`\\b${v}\\b`).test(rhs)) {
5793
+ taintedVars.add(lhs);
5794
+ break;
5795
+ }
5796
+ }
5797
+ }
5798
+ if (taintedVars.size === before)
5799
+ break;
5800
+ }
5801
+ if (taintedVars.size === 0)
5802
+ continue;
5803
+ for (let i = fn.start; i <= fn.end; i++) {
5804
+ const line = lines[i];
5805
+ const m = callHeadRe.exec(line);
5806
+ if (!m)
5807
+ continue;
5808
+ const op = m[1];
5809
+ const openIdx = m.index + m[0].length - 1;
5810
+ const args = extractBalanced(line, openIdx);
5811
+ if (args === null || args.length === 0)
5812
+ continue;
5813
+ let tainted = reqExtractRe.test(args);
5814
+ if (!tainted) {
5815
+ for (const v of taintedVars) {
5816
+ if (new RegExp(`\\b${v}\\b`).test(args)) {
5817
+ tainted = true;
5818
+ break;
5819
+ }
5820
+ }
5821
+ }
5822
+ if (!tainted)
5823
+ continue;
5824
+ findings.push({
5825
+ id: `nosql_injection-${file}-${i + 1}-go-mongo-${op.toLowerCase()}`,
5826
+ pass: 'language-sources',
5827
+ category: 'security',
5828
+ rule_id: 'nosql_injection',
5829
+ cwe: 'CWE-943',
5830
+ severity: 'critical',
5831
+ level: 'error',
5832
+ message: `NoSQL injection: Go MongoDB driver \`${op}(...)\` called with a ` +
5833
+ 'filter derived from *http.Request input. Untrusted values inside ' +
5834
+ 'a `bson.M` / `bson.D` filter can be operator objects (e.g. ' +
5835
+ '`{"$ne": null}`) and bypass authentication/intent. Validate or ' +
5836
+ 'coerce the value to a primitive before building the filter.',
5837
+ file,
5838
+ line: i + 1,
5839
+ snippet: line.trim(),
5840
+ });
5841
+ }
5842
+ }
5843
+ return findings;
5844
+ }
5845
+ /**
5846
+ * Sprint 84 detector B (#189) — Java Mongo driver nosql_injection.
5847
+ * Mongo Java driver shape `users.find(eq("k", <taint>))` (and siblings)
5848
+ * is not modeled by configured sinks (those cover Node.js Mongo only).
5849
+ * Fires when the receiver call payload references a value transitively
5850
+ * derived from servlet request extractors (request.getParameter /
5851
+ * getHeader / getCookies / getReader / getQueryString / getPart).
5852
+ */
5853
+ export function findJavaMongoNosqlInjectionFindings(code, file) {
5854
+ const findings = [];
5855
+ if (typeof code !== 'string' || code.length === 0)
5856
+ return findings;
5857
+ // Gate: require some hint of MongoCollection / Filters / Document use.
5858
+ if (!/(MongoCollection\b|com\.mongodb\b|\bFilters\b|\bnew\s+Document\s*\()/.test(code)) {
5859
+ return findings;
5860
+ }
5861
+ const lines = code.split('\n');
5862
+ const reqExtractRe = /\b\w+\s*\.\s*(?:getParameter|getParameterValues|getHeader|getHeaders|getCookies|getReader|getQueryString|getRequestURI|getInputStream|getPart|getParts)\s*\(/;
5863
+ const opsAlt = '(?:find|findOne|findOneAndUpdate|findOneAndDelete|findOneAndReplace|insertOne|insertMany|updateOne|updateMany|deleteOne|deleteMany|replaceOne|aggregate|countDocuments|distinct)';
5864
+ const callRe = new RegExp(`\\.\\s*(${opsAlt})\\s*\\(([\\s\\S]*?)\\)`);
5865
+ // Whole-file 3-pass taint propagation across simple `Type name = expr;`
5866
+ // and `name = expr;` assignments. Lightweight; suitable for the fixture
5867
+ // set without paying for full Java scope tracking.
5868
+ const taintedVars = new Set();
5869
+ for (let pass = 0; pass < 3; pass++) {
5870
+ const before = taintedVars.size;
5871
+ for (let i = 0; i < lines.length; i++) {
5872
+ const t = lines[i].trim();
5873
+ const a = t.match(/^(?:final\s+)?(?:[\w<>?,\[\]]+\s+)?(\w+)\s*=\s*(.+?);?$/);
5874
+ if (!a)
5875
+ continue;
5876
+ const lhs = a[1];
5877
+ const rhs = a[2];
5878
+ if (taintedVars.has(lhs))
5879
+ continue;
5880
+ if (reqExtractRe.test(rhs)) {
5881
+ taintedVars.add(lhs);
5882
+ continue;
5883
+ }
5884
+ for (const v of taintedVars) {
5885
+ if (new RegExp(`\\b${v}\\b`).test(rhs)) {
5886
+ taintedVars.add(lhs);
5887
+ break;
5888
+ }
5889
+ }
5890
+ }
5891
+ if (taintedVars.size === before)
5892
+ break;
5893
+ }
5894
+ if (taintedVars.size === 0)
5895
+ return findings;
5896
+ for (let i = 0; i < lines.length; i++) {
5897
+ const line = lines[i];
5898
+ const m = line.match(callRe);
5899
+ if (!m)
5900
+ continue;
5901
+ const op = m[1];
5902
+ const args = m[2];
5903
+ if (args.trim().length === 0)
5904
+ continue;
5905
+ let tainted = reqExtractRe.test(args);
5906
+ if (!tainted) {
5907
+ for (const v of taintedVars) {
5908
+ if (new RegExp(`\\b${v}\\b`).test(args)) {
5909
+ tainted = true;
5910
+ break;
5911
+ }
5912
+ }
5913
+ }
5914
+ if (!tainted)
5915
+ continue;
5916
+ findings.push({
5917
+ id: `nosql_injection-${file}-${i + 1}-java-mongo-${op.toLowerCase()}`,
5918
+ pass: 'language-sources',
5919
+ category: 'security',
5920
+ rule_id: 'nosql_injection',
5921
+ cwe: 'CWE-943',
5922
+ severity: 'critical',
5923
+ level: 'error',
5924
+ message: `NoSQL injection: Java Mongo driver \`${op}(...)\` called with a ` +
5925
+ 'filter derived from servlet request input. Untrusted values can ' +
5926
+ 'reach BSON operator positions and bypass intent. Validate the ' +
5927
+ 'input type before constructing the filter (e.g. require String).',
5928
+ file,
5929
+ line: i + 1,
5930
+ snippet: line.trim(),
5931
+ });
5932
+ }
5933
+ return findings;
5934
+ }
5935
+ /**
5936
+ * Sprint 84 detector C (#189) — Python mongoengine `$where` JS-string injection.
5937
+ * The shape `User.objects(__raw__={'$where': "this.x == '" + n + "'"})`
5938
+ * (and aliases via `$where` key with string concat / f-string) bypasses
5939
+ * the configured nosql sinks. Fires when the `$where` value references
5940
+ * a value transitively derived from Flask/Django/FastAPI request input.
5941
+ */
5942
+ export function findPythonMongoengineWhereNosqlInjectionFindings(code, file) {
5943
+ const findings = [];
5944
+ if (typeof code !== 'string' || code.length === 0)
5945
+ return findings;
5946
+ // Gate: require literal '$where' to appear in the file.
5947
+ if (!/['"]\$where['"]/.test(code))
5948
+ return findings;
5949
+ const lines = code.split('\n');
5950
+ const reqExtractRe = /\b(?:request\.(?:args|form|values|json|files|cookies|headers|data)\b|flask\.request\b)/;
5951
+ const taintedVars = new Set();
5952
+ for (let pass = 0; pass < 3; pass++) {
5953
+ const before = taintedVars.size;
5954
+ for (let i = 0; i < lines.length; i++) {
5955
+ const t = lines[i].trim();
5956
+ if (t.startsWith('#'))
5957
+ continue;
5958
+ const a = t.match(/^(\w+)\s*=\s*(.+?)$/);
5959
+ if (!a)
5960
+ continue;
5961
+ const lhs = a[1];
5962
+ const rhs = a[2];
5963
+ if (taintedVars.has(lhs))
5964
+ continue;
5965
+ if (reqExtractRe.test(rhs)) {
5966
+ taintedVars.add(lhs);
5967
+ continue;
5968
+ }
5969
+ for (const v of taintedVars) {
5970
+ if (new RegExp(`\\b${v}\\b`).test(rhs)) {
5971
+ taintedVars.add(lhs);
5972
+ break;
5973
+ }
5974
+ }
5975
+ }
5976
+ if (taintedVars.size === before)
5977
+ break;
5978
+ }
5979
+ const whereRe = /['"]\$where['"]\s*:\s*([^,}\n]+)/;
5980
+ for (let i = 0; i < lines.length; i++) {
5981
+ const line = lines[i];
5982
+ const m = line.match(whereRe);
5983
+ if (!m)
5984
+ continue;
5985
+ const valueExpr = m[1].trim();
5986
+ // Pure string literal (no concat, no f-string interp): safe.
5987
+ if (/^"[^"]*"$/.test(valueExpr) || /^'[^']*'$/.test(valueExpr))
5988
+ continue;
5989
+ let tainted = reqExtractRe.test(valueExpr);
5990
+ if (!tainted) {
5991
+ for (const v of taintedVars) {
5992
+ if (new RegExp(`\\b${v}\\b`).test(valueExpr)) {
5993
+ tainted = true;
5994
+ break;
5995
+ }
5996
+ }
5997
+ }
5998
+ if (!tainted)
5999
+ continue;
6000
+ findings.push({
6001
+ id: `nosql_injection-${file}-${i + 1}-py-mongoengine-where`,
6002
+ pass: 'language-sources',
6003
+ category: 'security',
6004
+ rule_id: 'nosql_injection',
6005
+ cwe: 'CWE-943',
6006
+ severity: 'critical',
6007
+ level: 'error',
6008
+ message: 'NoSQL injection: mongoengine `__raw__={"$where": ...}` payload ' +
6009
+ 'derived from HTTP request input. The `$where` operator evaluates ' +
6010
+ 'JavaScript on the server; tainted string concatenation lets an ' +
6011
+ 'attacker inject arbitrary JS. Replace `$where` with field-based ' +
6012
+ 'operators or validate the input.',
6013
+ file,
6014
+ line: i + 1,
6015
+ snippet: line.trim(),
6016
+ });
6017
+ }
6018
+ return findings;
6019
+ }
5704
6020
  //# sourceMappingURL=language-sources-pass.js.map