circle-ir 4.9.21 → 4.9.23

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 (33) hide show
  1. package/dist/analysis/interprocedural.d.ts +0 -6
  2. package/dist/analysis/interprocedural.d.ts.map +1 -1
  3. package/dist/analysis/interprocedural.js +64 -0
  4. package/dist/analysis/interprocedural.js.map +1 -1
  5. package/dist/analysis/modelled-cwes.d.ts +35 -0
  6. package/dist/analysis/modelled-cwes.d.ts.map +1 -0
  7. package/dist/analysis/modelled-cwes.js +63 -0
  8. package/dist/analysis/modelled-cwes.js.map +1 -0
  9. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  10. package/dist/analysis/passes/language-sources-pass.js +184 -0
  11. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  12. package/dist/analysis/passes/xml-entity-expansion-pass.d.ts +46 -3
  13. package/dist/analysis/passes/xml-entity-expansion-pass.d.ts.map +1 -1
  14. package/dist/analysis/passes/xml-entity-expansion-pass.js +139 -13
  15. package/dist/analysis/passes/xml-entity-expansion-pass.js.map +1 -1
  16. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  17. package/dist/analysis/taint-matcher.js +56 -0
  18. package/dist/analysis/taint-matcher.js.map +1 -1
  19. package/dist/browser/circle-ir.js +371 -17
  20. package/dist/core/circle-ir-core.cjs +24 -0
  21. package/dist/core/circle-ir-core.js +24 -0
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +3 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/languages/plugins/go.d.ts.map +1 -1
  27. package/dist/languages/plugins/go.js +21 -2
  28. package/dist/languages/plugins/go.js.map +1 -1
  29. package/dist/languages/plugins/index.d.ts +8 -0
  30. package/dist/languages/plugins/index.d.ts.map +1 -1
  31. package/dist/languages/plugins/index.js +21 -9
  32. package/dist/languages/plugins/index.js.map +1 -1
  33. package/package.json +1 -1
@@ -16257,6 +16257,27 @@ function classifyGoDestinationType(decl) {
16257
16257
  if (/\bany\b/.test(text)) return "unsafe";
16258
16258
  return "safe";
16259
16259
  }
16260
+ function isGoFprintToNonResponseWriter(call, pattern, language, sourceLines) {
16261
+ if (language !== "go") return false;
16262
+ if (pattern.type !== "xss" || pattern.class !== "fmt") return false;
16263
+ if (!/^Fprint(?:f|ln)?$/.test(call.method_name)) return false;
16264
+ if (!sourceLines) return true;
16265
+ const writer = call.arguments.find((a) => a.position === 0);
16266
+ const name2 = (writer?.expression ?? "").trim();
16267
+ if (!/^[A-Za-z_]\w*$/.test(name2)) return true;
16268
+ const rwRe = new RegExp(`\\b${name2}\\s+(?:net/)?http\\.ResponseWriter\\b`);
16269
+ for (let i2 = call.location.line - 1; i2 >= 0; i2--) {
16270
+ const line = sourceLines[i2] ?? "";
16271
+ const funcIdx = line.search(/\bfunc\b/);
16272
+ if (funcIdx < 0) continue;
16273
+ const header = sourceLines.slice(i2, i2 + 4).join(" ");
16274
+ const brace = header.indexOf("{");
16275
+ const params = header.slice(funcIdx, brace >= 0 ? brace : header.length);
16276
+ if (rwRe.test(params)) return false;
16277
+ if (/^\s*func\b/.test(line)) return true;
16278
+ }
16279
+ return true;
16280
+ }
16260
16281
  function isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines) {
16261
16282
  if (language !== "go") return false;
16262
16283
  if (pattern.type !== "deserialization") return false;
@@ -16389,6 +16410,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
16389
16410
  if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
16390
16411
  continue;
16391
16412
  }
16413
+ if (isGoFprintToNonResponseWriter(call, pattern, language, sourceLines)) {
16414
+ continue;
16415
+ }
16392
16416
  if (isSafeJinjaRenderCall(call, pattern, language, sourceLines)) {
16393
16417
  continue;
16394
16418
  }
@@ -19216,6 +19240,114 @@ function buildTaintFlow(source, sink, taintInfo) {
19216
19240
  }
19217
19241
 
19218
19242
  // src/analysis/interprocedural.ts
19243
+ var GO_BUILTIN_CALLS = /* @__PURE__ */ new Set([
19244
+ "len",
19245
+ "cap",
19246
+ "make",
19247
+ "new",
19248
+ "append",
19249
+ "copy",
19250
+ "delete",
19251
+ "close",
19252
+ "panic",
19253
+ "recover",
19254
+ "print",
19255
+ "println",
19256
+ "min",
19257
+ "max",
19258
+ "clear",
19259
+ "string",
19260
+ "int",
19261
+ "int8",
19262
+ "int16",
19263
+ "int32",
19264
+ "int64",
19265
+ "uint",
19266
+ "uint8",
19267
+ "uint16",
19268
+ "uint32",
19269
+ "uint64",
19270
+ "float32",
19271
+ "float64",
19272
+ "bool",
19273
+ "byte",
19274
+ "rune",
19275
+ "error"
19276
+ ]);
19277
+ var GO_ERROR_AND_LOG_CALLS = /* @__PURE__ */ new Set([
19278
+ "Errorf",
19279
+ // string formatting that returns a string
19280
+ "Sprintf",
19281
+ "Sprint",
19282
+ "Sprintln",
19283
+ // logging verbs (stdlib log, klog/glog, logrus, zap, zerolog)
19284
+ "Print",
19285
+ "Printf",
19286
+ "Println",
19287
+ "Fatal",
19288
+ "Fatalf",
19289
+ "Fatalln",
19290
+ "Panic",
19291
+ "Panicf",
19292
+ "Panicln",
19293
+ "Debug",
19294
+ "Debugf",
19295
+ "Debugln",
19296
+ "Debugw",
19297
+ "Info",
19298
+ "Infof",
19299
+ "Infoln",
19300
+ "Infow",
19301
+ "InfoS",
19302
+ "Warn",
19303
+ "Warnf",
19304
+ "Warnln",
19305
+ "Warnw",
19306
+ "Warning",
19307
+ "Warningf",
19308
+ "Warningln",
19309
+ "Error",
19310
+ "Errorln",
19311
+ "Errorw",
19312
+ "ErrorS",
19313
+ "Trace",
19314
+ "Tracef",
19315
+ "V",
19316
+ "WithError",
19317
+ "WithField",
19318
+ "WithFields",
19319
+ "WithValues",
19320
+ "Msg",
19321
+ "Msgf"
19322
+ ]);
19323
+ var GO_ERROR_PACKAGES = /* @__PURE__ */ new Set(["errors", "status", "xerrors", "multierr", "multierror"]);
19324
+ var GO_PURE_PACKAGES = /* @__PURE__ */ new Set([
19325
+ "strings",
19326
+ "strconv",
19327
+ "bytes",
19328
+ "unicode",
19329
+ "utf8",
19330
+ "path",
19331
+ "filepath",
19332
+ "math",
19333
+ "sort",
19334
+ "slices",
19335
+ "maps",
19336
+ "time",
19337
+ "regexp",
19338
+ "url",
19339
+ "hex",
19340
+ "base64"
19341
+ ]);
19342
+ function isGoNonEscapeCall(call) {
19343
+ const name2 = call.method_name;
19344
+ const recv = (call.receiver ?? "").split(".").pop() ?? "";
19345
+ if (!call.receiver && GO_BUILTIN_CALLS.has(name2)) return true;
19346
+ if (GO_ERROR_PACKAGES.has(recv)) return true;
19347
+ if (GO_PURE_PACKAGES.has(recv)) return true;
19348
+ if (GO_ERROR_AND_LOG_CALLS.has(name2)) return true;
19349
+ return false;
19350
+ }
19219
19351
  function analyzeInterprocedural(graphOrTypes, callsOrSources, dfgOrSinks, sourcesOrSanitizers, sinksOrOptions, sanitizersArg, optionsArg = {}) {
19220
19352
  let graph;
19221
19353
  let sources;
@@ -19470,6 +19602,9 @@ function analyzeInterprocedural(graphOrTypes, callsOrSources, dfgOrSinks, source
19470
19602
  if (!targetMethod) {
19471
19603
  if (taintedArgPositions.length > 0 && !collectionMethods.has(call.method_name) && !sanitizerMethods.has(call.method_name) && !safeUtilityMethods.has(call.method_name) && !ormQueryBuilderMethods.has(call.method_name)) {
19472
19604
  const isBash = graph.ir.meta.language === "bash";
19605
+ if (graph.ir.meta.language === "go" && isGoNonEscapeCall(call)) {
19606
+ continue;
19607
+ }
19473
19608
  const bashSafeBuiltins = /* @__PURE__ */ new Set([
19474
19609
  "echo",
19475
19610
  "printf",
@@ -25924,14 +26059,33 @@ var GoPlugin = class extends BaseLanguagePlugin {
25924
26059
  // rather than content — a weaker finding that would fire on every
25925
26060
  // path-validation helper that stats before opening, including the
25926
26061
  // correct ones. Left out until there is corpus evidence it pays.
25927
- // XSS (writing to http.ResponseWriter without escaping)
26062
+ // XSS (writing to http.ResponseWriter without escaping). The format
26063
+ // string AND the varargs — `Fprintf(w, "%s", q)` is the common shape
26064
+ // (#456). Gated in taint-matcher on arg[0] resolving to an
26065
+ // http.ResponseWriter parameter, so `Fprintf(os.Stderr, …)` is not xss.
25928
26066
  {
25929
26067
  method: "Fprintf",
25930
26068
  class: "fmt",
25931
26069
  type: "xss",
25932
26070
  cwe: "CWE-79",
25933
26071
  severity: "high",
25934
- argPositions: [1]
26072
+ argPositions: [1, 2, 3, 4, 5, 6]
26073
+ },
26074
+ {
26075
+ method: "Fprint",
26076
+ class: "fmt",
26077
+ type: "xss",
26078
+ cwe: "CWE-79",
26079
+ severity: "high",
26080
+ argPositions: [1, 2, 3, 4, 5, 6]
26081
+ },
26082
+ {
26083
+ method: "Fprintln",
26084
+ class: "fmt",
26085
+ type: "xss",
26086
+ cwe: "CWE-79",
26087
+ severity: "high",
26088
+ argPositions: [1, 2, 3, 4, 5, 6]
25935
26089
  },
25936
26090
  {
25937
26091
  method: "Write",
@@ -26446,16 +26600,21 @@ var CSharpPlugin = class extends BaseLanguagePlugin {
26446
26600
  };
26447
26601
 
26448
26602
  // src/languages/plugins/index.ts
26603
+ function createBuiltinPlugins() {
26604
+ return [
26605
+ new JavaPlugin(),
26606
+ new JavaScriptPlugin(),
26607
+ new PythonPlugin(),
26608
+ new RustPlugin(),
26609
+ new BashPlugin(),
26610
+ new HtmlPlugin(),
26611
+ new VuePlugin(),
26612
+ new GoPlugin(),
26613
+ new CSharpPlugin()
26614
+ ];
26615
+ }
26449
26616
  function registerBuiltinPlugins() {
26450
- registerLanguage(new JavaPlugin());
26451
- registerLanguage(new JavaScriptPlugin());
26452
- registerLanguage(new PythonPlugin());
26453
- registerLanguage(new RustPlugin());
26454
- registerLanguage(new BashPlugin());
26455
- registerLanguage(new HtmlPlugin());
26456
- registerLanguage(new VuePlugin());
26457
- registerLanguage(new GoPlugin());
26458
- registerLanguage(new CSharpPlugin());
26617
+ for (const plugin of createBuiltinPlugins()) registerLanguage(plugin);
26459
26618
  }
26460
26619
 
26461
26620
  // src/analysis/html/html-extractor.ts
@@ -27330,6 +27489,8 @@ var LanguageSourcesPass = class {
27330
27489
  additionalSources.push(...findGoArgvSources(code, language));
27331
27490
  additionalSources.push(...findGoArchiveEntrySources(code, language));
27332
27491
  additionalSources.push(...findGoMultipartUploadSources(code, language));
27492
+ additionalSources.push(...findGoGrpcRequestSources(code, language));
27493
+ additionalSources.push(...findGoRequestBodySources(code, language));
27333
27494
  const jsDOMSinks = findJavaScriptDOMSinks(code, language);
27334
27495
  for (const s of jsDOMSinks) {
27335
27496
  const alreadyExists = additionalSinks.some((x) => x.line === s.line && x.cwe === s.cwe);
@@ -28107,6 +28268,121 @@ function findGoMultipartUploadSources(sourceCode, language) {
28107
28268
  }
28108
28269
  return sources;
28109
28270
  }
28271
+ function findGoGrpcRequestSources(sourceCode, language) {
28272
+ if (language !== "go") return [];
28273
+ if (!sourceCode.includes("context.Context")) return [];
28274
+ const sources = [];
28275
+ const lines = sourceCode.split("\n");
28276
+ const sigRe = /^func\s*\([^)]*\)\s*[A-Z]\w*\s*\(\s*\w+\s+context\.Context\s*,\s*([A-Za-z_]\w*)\s+\*(?:\w+\.)?\w*(?:Request|Req)\s*\)\s*\(\s*\*[\w.]+\s*,\s*error\s*\)\s*\{/;
28277
+ const controlRe = /^\s*(?:\}\s*else\s+)?(?:if|for|switch|case|return)\b/;
28278
+ for (let i2 = 0; i2 < lines.length; i2++) {
28279
+ const sig = sigRe.exec(lines[i2]);
28280
+ if (!sig) continue;
28281
+ const param = sig[1];
28282
+ if (param === "_") continue;
28283
+ const readRe = new RegExp(
28284
+ `(?<![\\w.])${param}\\s*\\.\\s*(?:Get[A-Z]\\w*\\s*\\(\\s*\\)|[A-Z]\\w*\\b(?!\\s*\\())`
28285
+ );
28286
+ const directReadRe = new RegExp(
28287
+ `^(?:(?:\\[\\]\\w+|string)\\s*\\(\\s*)*${param}(?:\\s*\\.\\s*(?:Get[A-Z]\\w*\\s*\\(\\s*\\)|[A-Z]\\w*\\b(?!\\s*\\()))+(?:\\s*\\))*$`
28288
+ );
28289
+ const numericParseRe = new RegExp(
28290
+ `\\bstrconv\\s*\\.\\s*(?:Atoi|ParseInt|ParseUint|ParseFloat|ParseBool)\\s*\\(\\s*${param}\\s*\\.`
28291
+ );
28292
+ let end = i2 + 1;
28293
+ while (end < lines.length && !/^\}/.test(lines[end])) end++;
28294
+ for (let j = i2 + 1; j < end; j++) {
28295
+ const line = lines[j];
28296
+ const read = readRe.exec(line);
28297
+ if (!read) continue;
28298
+ if (numericParseRe.test(line)) continue;
28299
+ let variable;
28300
+ const unmarshal = /\bUnmarshal\w*\s*\([^&]*&\s*([A-Za-z_]\w*)/.exec(line);
28301
+ const assign = /^\s*(?:var\s+)?([A-Za-z_][\w\s,]*?)\s*:?=(?!=)\s*(.+)$/.exec(line);
28302
+ if (unmarshal && line.indexOf(read[0]) < line.indexOf("&")) {
28303
+ variable = unmarshal[1];
28304
+ } else if (assign && directReadRe.test(assign[2].trim()) && !controlRe.test(line)) {
28305
+ variable = assign[1].split(",").map((v) => v.trim()).find((v) => v !== "_" && v !== "err" && v !== "ok" && /^[A-Za-z_]\w*$/.test(v));
28306
+ if (!variable) continue;
28307
+ } else if (controlRe.test(line)) {
28308
+ continue;
28309
+ } else {
28310
+ variable = param;
28311
+ }
28312
+ const lineNumber = j + 1;
28313
+ if (sources.some((sc) => sc.line === lineNumber && sc.variable === variable)) continue;
28314
+ sources.push({
28315
+ type: "http_body",
28316
+ location: `${read[0].replace(/\s+/g, "")} \u2014 field of the gRPC request message \`${param}\``,
28317
+ severity: "high",
28318
+ line: lineNumber,
28319
+ confidence: 0.85,
28320
+ variable
28321
+ });
28322
+ }
28323
+ i2 = end;
28324
+ }
28325
+ return sources;
28326
+ }
28327
+ function findGoRequestBodySources(sourceCode, language) {
28328
+ if (language !== "go") return [];
28329
+ if (!sourceCode.includes(".Body")) return [];
28330
+ const lines = sourceCode.split("\n");
28331
+ const reqNames = /* @__PURE__ */ new Set();
28332
+ const paramRe = /([A-Za-z_]\w*)\s+\*http\.Request\b/g;
28333
+ for (const line of lines) {
28334
+ let m;
28335
+ paramRe.lastIndex = 0;
28336
+ while ((m = paramRe.exec(line)) !== null) reqNames.add(m[1]);
28337
+ }
28338
+ if (reqNames.size === 0) return [];
28339
+ const bodyAlt = [...reqNames].map((n) => n.replace(/\$/g, "\\$")).join("|");
28340
+ const bodyRef = `(?<![\\w.])(?:${bodyAlt})\\s*\\.\\s*Body\\b`;
28341
+ const sources = [];
28342
+ const push = (variable, line, how) => {
28343
+ if (variable === "_" || variable === "") return;
28344
+ if (sources.some((s) => s.line === line && s.variable === variable)) return;
28345
+ sources.push({
28346
+ type: "http_body",
28347
+ location: `${how} \u2014 HTTP request body`,
28348
+ severity: "high",
28349
+ line,
28350
+ confidence: 0.85,
28351
+ ...variable ? { variable } : {}
28352
+ });
28353
+ };
28354
+ const bodyRe = new RegExp(bodyRef);
28355
+ const decodeRe = new RegExp(
28356
+ `(?:json|xml)\\s*\\.\\s*NewDecoder\\s*\\(\\s*(?:io\\.NopCloser\\s*\\(\\s*)?(?:${bodyAlt})\\s*\\.\\s*Body\\b[^)]*\\)\\s*\\)?\\s*\\.\\s*Decode\\s*\\(\\s*&\\s*([A-Za-z_]\\w*)`
28357
+ );
28358
+ const readAllRe = new RegExp(
28359
+ `\\b([A-Za-z_]\\w*)\\s*,\\s*\\w+\\s*:?=\\s*(?:io|ioutil)\\s*\\.\\s*ReadAll\\s*\\(\\s*(?:${bodyAlt})\\s*\\.\\s*Body\\b`
28360
+ );
28361
+ const copyRe = new RegExp(
28362
+ `\\bio\\s*\\.\\s*Copy\\s*\\(\\s*([A-Za-z_]\\w*|&\\s*[A-Za-z_]\\w*)\\s*,\\s*(?:${bodyAlt})\\s*\\.\\s*Body\\b`
28363
+ );
28364
+ for (let i2 = 0; i2 < lines.length; i2++) {
28365
+ const line = lines[i2];
28366
+ if (!bodyRe.test(line)) continue;
28367
+ const n = i2 + 1;
28368
+ const dec = decodeRe.exec(line);
28369
+ if (dec) {
28370
+ push(dec[1], n, `json/xml decode of ${dec[0].split(".")[0]}.Body`);
28371
+ continue;
28372
+ }
28373
+ const ra = readAllRe.exec(line);
28374
+ if (ra) {
28375
+ push(ra[1], n, "io.ReadAll(req.Body)");
28376
+ continue;
28377
+ }
28378
+ const cp = copyRe.exec(line);
28379
+ if (cp) {
28380
+ push(cp[1].replace(/^&\s*/, ""), n, "io.Copy(dst, req.Body)");
28381
+ continue;
28382
+ }
28383
+ }
28384
+ return sources;
28385
+ }
28110
28386
  function findCSharpRequestSources(sourceCode, language) {
28111
28387
  if (language !== "csharp") return [];
28112
28388
  const sources = [];
@@ -46241,6 +46517,8 @@ var JAVA_XML_OUTPUT_ONLY_RE = /\bnew\s+(?:DOMSource|StreamResult)\s*\(/;
46241
46517
  var JAVA_XML_PARSE_INPUT_RE = /\bnew\s+(?:StreamSource|SAXSource|InputSource)\s*\(/;
46242
46518
  var JAVA_DOC_BUILDER_NEW_DOCUMENT_RE = /\.\s*newDocument\s*\(\s*\)/;
46243
46519
  var JAVA_DOC_BUILDER_PARSE_RE = /(?:DocumentBuilder|builder)\s*\.\s*parse\s*\(/;
46520
+ var JAVA_HARDENING_SETTER_RE = /\.\s*(?:setFeature|setAttribute|setProperty|setXIncludeAware|setExpandEntityReferences)\s*\(/;
46521
+ var JAVA_FACTORY_CHAINED_RE = /\bnewInstance\s*\([^()]*\)\s*\.\s*(?:newDocumentBuilder|newSAXParser|newTransformer|newTemplates|newSchema|createXMLStreamReader|createXMLEventReader)\s*\(/;
46244
46522
  var PY_LXML_PARSER_INSECURE_DEFAULT_RE = /\bresolve_entities\s*=\s*False\b/;
46245
46523
  var XmlEntityExpansionPass = class {
46246
46524
  name = "xml-entity-expansion";
@@ -46252,7 +46530,9 @@ var XmlEntityExpansionPass = class {
46252
46530
  const code = ctx.code ?? "";
46253
46531
  if (language === "java") {
46254
46532
  const safeInFile = JAVA_SAFE_EVIDENCE_RE.test(code);
46255
- if (safeInFile) return { findings };
46533
+ const processWide = safeInFile && /jdk\.xml\./.test(code);
46534
+ const lines = safeInFile ? code.split("\n") : [];
46535
+ const methodRanges = safeInFile ? this.methodRanges(graph.ir.types) : [];
46256
46536
  const isXmlOutputOnly = JAVA_XML_OUTPUT_ONLY_RE.test(code) && !JAVA_XML_PARSE_INPUT_RE.test(code);
46257
46537
  const isDocumentBuilderEmptyOnly = JAVA_DOC_BUILDER_NEW_DOCUMENT_RE.test(code) && !JAVA_DOC_BUILDER_PARSE_RE.test(code);
46258
46538
  for (const call of graph.ir.calls) {
@@ -46262,6 +46542,8 @@ var XmlEntityExpansionPass = class {
46262
46542
  if (det.api === "DocumentBuilderFactory" && isDocumentBuilderEmptyOnly)
46263
46543
  continue;
46264
46544
  const line = call.location.line;
46545
+ if (safeInFile && (processWide || !this.isProvablyUnhardened(lines, line, methodRanges, det.api)))
46546
+ continue;
46265
46547
  findings.push({ line, language, ...det });
46266
46548
  ctx.addFinding({
46267
46549
  id: `${this.name}-${file}-${line}-${det.api}`,
@@ -46271,11 +46553,11 @@ var XmlEntityExpansionPass = class {
46271
46553
  cwe: det.cwe,
46272
46554
  severity: "high",
46273
46555
  level: "error",
46274
- message: `${det.api} created without disabling DTD / external-entity processing. Vulnerable to billion-laughs / quadratic blow-up DoS (CWE-776) and external-entity disclosure (CWE-611). Add \`setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)\` (or the equivalent) before parsing.`,
46556
+ message: `${det.api} created without disabling DTD / external-entity processing. Vulnerable to external-entity disclosure (CWE-611) and billion-laughs / quadratic blow-up DoS (CWE-776). Add \`setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)\` (or the equivalent) before parsing.`,
46275
46557
  file,
46276
46558
  line,
46277
46559
  fix: this.fixForJava(det.api),
46278
- evidence: { ...det, language, safeFeatureInFile: false }
46560
+ evidence: { ...det, language, safeFeatureInFile: safeInFile }
46279
46561
  });
46280
46562
  }
46281
46563
  return { findings };
@@ -46296,7 +46578,7 @@ var XmlEntityExpansionPass = class {
46296
46578
  cwe: det.cwe,
46297
46579
  severity: "high",
46298
46580
  level: "error",
46299
- message: `${det.api} called without an entity-safe parser. Vulnerable to billion-laughs / quadratic blow-up DoS (CWE-776) and external-entity disclosure (CWE-611). Use \`defusedxml\` or pass an \`XMLParser(resolve_entities=False)\` to lxml.`,
46581
+ message: `${det.api} called without an entity-safe parser. Vulnerable ` + (det.cwe === "CWE-611" ? "to external-entity disclosure (CWE-611) and billion-laughs / quadratic blow-up DoS (CWE-776). " : "to billion-laughs / quadratic blow-up DoS (CWE-776). ") + "Use `defusedxml` or pass an `XMLParser(resolve_entities=False)` to lxml.",
46300
46582
  file,
46301
46583
  line,
46302
46584
  fix: this.fixForPython(det.api),
@@ -46307,6 +46589,78 @@ var XmlEntityExpansionPass = class {
46307
46589
  }
46308
46590
  return { findings };
46309
46591
  }
46592
+ methodRanges(types) {
46593
+ const out2 = [];
46594
+ for (const t of types ?? []) {
46595
+ for (const m of t.methods ?? []) {
46596
+ if (typeof m.start_line === "number" && typeof m.end_line === "number")
46597
+ out2.push([m.start_line, m.end_line]);
46598
+ }
46599
+ }
46600
+ return out2;
46601
+ }
46602
+ /**
46603
+ * In a file that DOES contain hardening evidence, is the factory created on
46604
+ * `line` one that provably never receives it?
46605
+ *
46606
+ * Deliberately one-sided. It answers true for exactly two shapes:
46607
+ *
46608
+ * 1. CHAINED — `Factory.newInstance().newDocumentBuilder()`, where the
46609
+ * product is not handed on or returned either.
46610
+ * 2. LOCAL — `Factory f = Factory.newInstance();` where the enclosing method
46611
+ * builds a parser from `f`, never hands `f` to another call, and never
46612
+ * returns it.
46613
+ *
46614
+ * and in both only when the enclosing method contains NO hardening-capable
46615
+ * setter on ANY receiver, since hardening may land on the factory's product
46616
+ * (`parser.getXMLReader().setFeature(…)`) rather than the factory.
46617
+ *
46618
+ * Every other shape — a field, a helper that takes the factory, a caller that
46619
+ * receives it — may be hardened somewhere this check cannot see, so it keeps
46620
+ * the previous file-level silence.
46621
+ *
46622
+ * A TransformerFactory additionally needs a `StreamSource` in its method: that
46623
+ * is the input the transformer parses with its OWN parser. Fed a `DOMSource`
46624
+ * it parses nothing, and fed a `SAXSource` it uses the reader it was given —
46625
+ * whose hardening is that reader's business, not this factory's.
46626
+ */
46627
+ isProvablyUnhardened(lines, line, methodRanges, api) {
46628
+ let range = null;
46629
+ for (const r of methodRanges) {
46630
+ if (line < r[0] || line > r[1]) continue;
46631
+ if (!range || r[1] - r[0] < range[1] - range[0]) range = r;
46632
+ }
46633
+ if (!range) return false;
46634
+ let decl = "";
46635
+ let declEnd = line;
46636
+ for (; declEnd <= Math.min(line + 3, range[1]); declEnd++) {
46637
+ decl += " " + (lines[declEnd - 1] ?? "").trim();
46638
+ if (decl.includes(";")) break;
46639
+ }
46640
+ const body2 = lines.slice(line - 1, range[1]).join("\n");
46641
+ if (api === "TransformerFactory" && !/\bnew\s+StreamSource\s*\(/.test(body2))
46642
+ return false;
46643
+ if (JAVA_HARDENING_SETTER_RE.test(body2)) return false;
46644
+ const chained = JAVA_FACTORY_CHAINED_RE.exec(decl);
46645
+ if (chained) {
46646
+ const prod = /[\w>\]]\s+([A-Za-z_$][\w$]*)\s*=/.exec(decl);
46647
+ if (!prod) return true;
46648
+ const pn = prod[1].replace(/\$/g, "\\$");
46649
+ const after = lines.slice(declEnd, range[1]).join("\n");
46650
+ return !new RegExp(`[(,]\\s*${pn}\\s*[,)]|\\breturn\\s+${pn}\\s*;`).test(after);
46651
+ }
46652
+ const m = /[\w>\]]\s+([A-Za-z_$][\w$]*)\s*=\s*[\w.]*\bnewInstance\s*\([^()]*\)\s*;/.exec(decl);
46653
+ if (!m) return false;
46654
+ const name2 = m[1].replace(/\$/g, "\\$");
46655
+ const rest = lines.slice(declEnd, range[1]).join("\n");
46656
+ const builds = new RegExp(
46657
+ `\\b${name2}\\s*\\.\\s*(?:newDocumentBuilder|newSAXParser|newTransformer|newTemplates|newSchema|createXMLStreamReader|createXMLEventReader)\\s*\\(`
46658
+ );
46659
+ if (!builds.test(rest)) return false;
46660
+ const escapes = new RegExp(`[(,]\\s*${name2}\\s*[,)]|\\breturn\\s+${name2}\\s*;`);
46661
+ if (escapes.test(rest)) return false;
46662
+ return true;
46663
+ }
46310
46664
  detectJavaCall(call) {
46311
46665
  if (call.method_name !== "newInstance") return null;
46312
46666
  const recv = call.receiver ?? "";
@@ -46316,7 +46670,7 @@ var XmlEntityExpansionPass = class {
46316
46670
  return {
46317
46671
  pattern: `${factory}.newInstance()`,
46318
46672
  api: factory,
46319
- cwe: "CWE-776"
46673
+ cwe: "CWE-611"
46320
46674
  };
46321
46675
  }
46322
46676
  }
@@ -46329,7 +46683,7 @@ var XmlEntityExpansionPass = class {
46329
46683
  return {
46330
46684
  pattern: `etree.${method}`,
46331
46685
  api: `lxml.etree.${method}`,
46332
- cwe: "CWE-776"
46686
+ cwe: "CWE-611"
46333
46687
  };
46334
46688
  }
46335
46689
  if ((method === "parse" || method === "fromstring") && (recv === "ET" || recv === "ElementTree" || recv.endsWith(".ElementTree"))) {
@@ -15557,6 +15557,27 @@ function classifyGoDestinationType(decl) {
15557
15557
  if (/\bany\b/.test(text)) return "unsafe";
15558
15558
  return "safe";
15559
15559
  }
15560
+ function isGoFprintToNonResponseWriter(call, pattern, language, sourceLines) {
15561
+ if (language !== "go") return false;
15562
+ if (pattern.type !== "xss" || pattern.class !== "fmt") return false;
15563
+ if (!/^Fprint(?:f|ln)?$/.test(call.method_name)) return false;
15564
+ if (!sourceLines) return true;
15565
+ const writer = call.arguments.find((a) => a.position === 0);
15566
+ const name2 = (writer?.expression ?? "").trim();
15567
+ if (!/^[A-Za-z_]\w*$/.test(name2)) return true;
15568
+ const rwRe = new RegExp(`\\b${name2}\\s+(?:net/)?http\\.ResponseWriter\\b`);
15569
+ for (let i2 = call.location.line - 1; i2 >= 0; i2--) {
15570
+ const line = sourceLines[i2] ?? "";
15571
+ const funcIdx = line.search(/\bfunc\b/);
15572
+ if (funcIdx < 0) continue;
15573
+ const header = sourceLines.slice(i2, i2 + 4).join(" ");
15574
+ const brace = header.indexOf("{");
15575
+ const params = header.slice(funcIdx, brace >= 0 ? brace : header.length);
15576
+ if (rwRe.test(params)) return false;
15577
+ if (/^\s*func\b/.test(line)) return true;
15578
+ }
15579
+ return true;
15580
+ }
15560
15581
  function isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines) {
15561
15582
  if (language !== "go") return false;
15562
15583
  if (pattern.type !== "deserialization") return false;
@@ -15689,6 +15710,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
15689
15710
  if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
15690
15711
  continue;
15691
15712
  }
15713
+ if (isGoFprintToNonResponseWriter(call, pattern, language, sourceLines)) {
15714
+ continue;
15715
+ }
15692
15716
  if (isSafeJinjaRenderCall(call, pattern, language, sourceLines)) {
15693
15717
  continue;
15694
15718
  }
@@ -15491,6 +15491,27 @@ function classifyGoDestinationType(decl) {
15491
15491
  if (/\bany\b/.test(text)) return "unsafe";
15492
15492
  return "safe";
15493
15493
  }
15494
+ function isGoFprintToNonResponseWriter(call, pattern, language, sourceLines) {
15495
+ if (language !== "go") return false;
15496
+ if (pattern.type !== "xss" || pattern.class !== "fmt") return false;
15497
+ if (!/^Fprint(?:f|ln)?$/.test(call.method_name)) return false;
15498
+ if (!sourceLines) return true;
15499
+ const writer = call.arguments.find((a) => a.position === 0);
15500
+ const name2 = (writer?.expression ?? "").trim();
15501
+ if (!/^[A-Za-z_]\w*$/.test(name2)) return true;
15502
+ const rwRe = new RegExp(`\\b${name2}\\s+(?:net/)?http\\.ResponseWriter\\b`);
15503
+ for (let i2 = call.location.line - 1; i2 >= 0; i2--) {
15504
+ const line = sourceLines[i2] ?? "";
15505
+ const funcIdx = line.search(/\bfunc\b/);
15506
+ if (funcIdx < 0) continue;
15507
+ const header = sourceLines.slice(i2, i2 + 4).join(" ");
15508
+ const brace = header.indexOf("{");
15509
+ const params = header.slice(funcIdx, brace >= 0 ? brace : header.length);
15510
+ if (rwRe.test(params)) return false;
15511
+ if (/^\s*func\b/.test(line)) return true;
15512
+ }
15513
+ return true;
15514
+ }
15494
15515
  function isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines) {
15495
15516
  if (language !== "go") return false;
15496
15517
  if (pattern.type !== "deserialization") return false;
@@ -15623,6 +15644,9 @@ function findSinks(calls, patterns, typeHierarchy, language, sourceLines, types)
15623
15644
  if (isSafeGoJsonUnmarshalCall(call, pattern, language, sourceLines)) {
15624
15645
  continue;
15625
15646
  }
15647
+ if (isGoFprintToNonResponseWriter(call, pattern, language, sourceLines)) {
15648
+ continue;
15649
+ }
15626
15650
  if (isSafeJinjaRenderCall(call, pattern, language, sourceLines)) {
15627
15651
  continue;
15628
15652
  }
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export type { UnboundedCollectionOptions } from './analysis/passes/unbounded-col
12
12
  export type { PassOptions } from './analyzer.js';
13
13
  export type { CircleIR, Meta, TypeInfo, MethodInfo, ParameterInfo, FieldInfo, CallInfo, ArgumentInfo, CallResolution, CFG, CFGBlock, CFGEdge, DFG, DFGDef, DFGUse, DFGChain, Taint, TaintSource, TaintSink, TaintSanitizer, ImportInfo, ExportInfo, UnresolvedItem, Enriched, EnrichedFunction, ResolvedCall, Finding, TaintHop, Vulnerability, AnalysisResponse, SourceType, SinkType, Severity, ProjectShape, ProjectEnv, ProjectProfile, ProjectProfileSummary, PassCategory, SarifLevel, SastFinding, MetricCategory, MetricValue, FileMetrics, ProjectAnalysis, ProjectMeta, FileAnalysis, TypeHierarchy, ClassHierarchyInfo, InterfaceHierarchyInfo, CrossFileCall, ArgMapping, TaintPath, } from './types/index.js';
14
14
  export { SOURCE_TYPES, SINK_TYPES } from './types/index.js';
15
+ export { getModelledCwes, isModelledCwe, RELATED_CWE, type ModelledCwes, } from './analysis/modelled-cwes.js';
15
16
  export type { SourceConfig, SinkConfig, TaintConfig, SourcePattern, SinkPattern, SanitizerPattern, } from './types/config.js';
16
17
  export { initParser, parse, walkTree, findNodes, findAncestor, getNodeText, collectAllNodes, type SupportedLanguage, type SyntaxNode, type Node, type NodeCache, type Tree, } from './core/index.js';
17
18
  export { extractMeta, extractTypes, extractCalls, extractImports, extractExports, buildCFG, buildDFG, } from './core/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,6 +16,9 @@ export { parseNpmDependencies, parseNpmLockDependencies, parsePypiDependencies,
16
16
  // an unmatched value fails a test on their side rather than falling through
17
17
  // to a default branch. Locked by tests/public-entry-exports.test.ts.
18
18
  export { SOURCE_TYPES, SINK_TYPES } from './types/index.js';
19
+ // Modelled-CWE export (#393) — which weakness classes the taint engine covers,
20
+ // derived from the live sink registries.
21
+ export { getModelledCwes, isModelledCwe, RELATED_CWE, } from './analysis/modelled-cwes.js';
19
22
  // Core utilities (for advanced usage)
20
23
  export { initParser, parse, walkTree, findNodes, findAncestor, getNodeText, collectAllNodes, } from './core/index.js';
21
24
  // Core extractors
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,GAEd,MAAM,eAAe,CAAC;AAEvB,4EAA4E;AAC5E,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,MAAM,GACP,MAAM,oBAAoB,CAAC;AA+E5B,sEAAsE;AACtE,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,qEAAqE;AACrE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAY5D,sCAAsC;AACtC,OAAO,EACL,UAAU,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,WAAW,EACX,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AAEzB,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,gCAAgC,EAChC,0BAA0B,EAC1B,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GAMnB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,iCAAiC,CAAC;AAExF,uBAAuB;AACvB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,mBAAmB;AACnB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAY9B,gCAAgC;AAChC,OAAO,EACL,MAAM,EACN,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,GAIZ,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,OAAO,EACP,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,GAEd,MAAM,eAAe,CAAC;AAEvB,4EAA4E;AAC5E,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,MAAM,GACP,MAAM,oBAAoB,CAAC;AA+E5B,sEAAsE;AACtE,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,qEAAqE;AACrE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5D,+EAA+E;AAC/E,yCAAyC;AACzC,OAAO,EACL,eAAe,EACf,aAAa,EACb,WAAW,GAEZ,MAAM,6BAA6B,CAAC;AAYrC,sCAAsC;AACtC,OAAO,EACL,UAAU,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,WAAW,EACX,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AAEzB,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,cAAc,EACd,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,gCAAgC,EAChC,0BAA0B,EAC1B,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,GAMnB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,iCAAiC,CAAC;AAExF,uBAAuB;AACvB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,mBAAmB;AACnB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAY9B,gCAAgC;AAChC,OAAO,EACL,MAAM,EACN,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,GAIZ,MAAM,mBAAmB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/languages/plugins/go.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,kBAAkB;IAC9C,QAAQ,CAAC,EAAE,EAAG,IAAI,CAAU;IAC5B,QAAQ,CAAC,IAAI,QAAQ;IACrB,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,QAAQ,yBAAyB;IAE1C,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CA+BnC;IAEF;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,GAAG,SAAS,CAsDrE;IAED;;OAEG;IACH,iBAAiB,IAAI,kBAAkB,EAAE,CAiGxC;IAED;;;;;;OAMG;IACH,eAAe,IAAI,gBAAgB,EAAE,CAkXpC;IAED;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAejF;IAED;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAGzC;IAED;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAgBnD;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,QAAQ,EAAE,CAwFnD;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,QAAQ,EAAE,CAoDnD;IAED;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,EAAE,CA2BvD;IAED;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAc7D;IAID,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,eAAe;CAiBxB"}
1
+ {"version":3,"file":"go.d.ts","sourceRoot":"","sources":["../../../src/languages/plugins/go.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,qBAAa,QAAS,SAAQ,kBAAkB;IAC9C,QAAQ,CAAC,EAAE,EAAG,IAAI,CAAU;IAC5B,QAAQ,CAAC,IAAI,QAAQ;IACrB,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,QAAQ,yBAAyB;IAE1C,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CA+BnC;IAEF;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,GAAG,SAAS,CAsDrE;IAED;;OAEG;IACH,iBAAiB,IAAI,kBAAkB,EAAE,CAiGxC;IAED;;;;;;OAMG;IACH,eAAe,IAAI,gBAAgB,EAAE,CAqYpC;IAED;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAejF;IAED;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAGzC;IAED;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAgBnD;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,QAAQ,EAAE,CAwFnD;IAED;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,QAAQ,EAAE,CAoDnD;IAED;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,EAAE,CA2BvD;IAED;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAc7D;IAID,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,eAAe;CAiBxB"}