mobbdev 1.4.12 → 1.4.15

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.
@@ -1037,7 +1037,7 @@ var init_client_generates = __esm({
1037
1037
  }
1038
1038
  `;
1039
1039
  DigestVulnerabilityReportDocument = `
1040
- mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String) {
1040
+ mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String, $baselineCommit: String) {
1041
1041
  digestVulnerabilityReport(
1042
1042
  fixReportId: $fixReportId
1043
1043
  vulnerabilityReportFileName: $vulnerabilityReportFileName
@@ -1046,6 +1046,7 @@ var init_client_generates = __esm({
1046
1046
  repoUrl: $repoUrl
1047
1047
  reference: $reference
1048
1048
  sha: $sha
1049
+ baselineCommit: $baselineCommit
1049
1050
  ) {
1050
1051
  __typename
1051
1052
  ... on VulnerabilityReport {
@@ -1262,14 +1263,14 @@ var init_client_generates = __esm({
1262
1263
  GetLatestReportByRepoUrlDocument = `
1263
1264
  query GetLatestReportByRepoUrl($repoUrl: String!, $filters: fix_bool_exp = {}, $limit: Int!, $offset: Int!, $currentUserEmail: String!) {
1264
1265
  fixReport(
1265
- where: {_and: [{repo: {originalUrl: {_eq: $repoUrl}}}, {state: {_eq: Finished}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1266
+ where: {_and: [{repo: {originalUrl: {_ilike: $repoUrl}}}, {state: {_eq: Finished}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1266
1267
  order_by: {createdOn: desc}
1267
1268
  limit: 1
1268
1269
  ) {
1269
1270
  ...FixReportSummaryFields
1270
1271
  }
1271
1272
  expiredReport: fixReport(
1272
- where: {_and: [{repo: {originalUrl: {_eq: $repoUrl}}}, {state: {_eq: Expired}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1273
+ where: {_and: [{repo: {originalUrl: {_ilike: $repoUrl}}}, {state: {_eq: Expired}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1273
1274
  order_by: {createdOn: desc}
1274
1275
  limit: 1
1275
1276
  ) {
@@ -1577,7 +1578,7 @@ var init_analysis = __esm({
1577
1578
 
1578
1579
  // src/features/analysis/scm/shared/src/types/issue.ts
1579
1580
  import { z as z4 } from "zod";
1580
- var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapBucketTypeToCategory;
1581
+ var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, UnfixablePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapBucketTypeToCategory;
1581
1582
  var init_issue = __esm({
1582
1583
  "src/features/analysis/scm/shared/src/types/issue.ts"() {
1583
1584
  "use strict";
@@ -1659,12 +1660,17 @@ var init_issue = __esm({
1659
1660
  return { codeDiff };
1660
1661
  })
1661
1662
  }).nullish(),
1662
- sharedState: VulnerabilityReportIssueSharedStateZ
1663
+ sharedState: VulnerabilityReportIssueSharedStateZ,
1664
+ unfixableId: z4.string().uuid().nullish()
1663
1665
  });
1664
1666
  FalsePositivePartsZ = z4.object({
1665
1667
  extraContext: z4.array(z4.object({ key: z4.string(), value: z4.string() })),
1666
1668
  fixDescription: z4.string()
1667
1669
  });
1670
+ UnfixablePartsZ = z4.object({
1671
+ extraContext: z4.array(z4.object({ key: z4.string(), value: z4.string() })),
1672
+ fixDescription: z4.string()
1673
+ });
1668
1674
  IssuePartsWithFixZ = BaseIssuePartsZ.merge(
1669
1675
  z4.object({
1670
1676
  category: z4.literal("Irrelevant" /* Irrelevant */),
@@ -1686,7 +1692,8 @@ var init_issue = __esm({
1686
1692
  z4.literal("Fixable" /* Fixable */),
1687
1693
  z4.literal("Filtered" /* Filtered */),
1688
1694
  z4.literal("Pending" /* Pending */)
1689
- ])
1695
+ ]),
1696
+ getUnfixable: UnfixablePartsZ.nullish()
1690
1697
  })
1691
1698
  );
1692
1699
  IssuePartsZ = z4.union([
@@ -4431,6 +4438,18 @@ if (!semver.satisfies(process.version, packageJson.engines.node)) {
4431
4438
 
4432
4439
  // src/utils/gitUtils.ts
4433
4440
  import simpleGit from "simple-git";
4441
+ var tag = (sink) => (data, msg) => {
4442
+ if (msg) {
4443
+ const sanitizedMsg = String(msg).replace(/\n|\r/g, "");
4444
+ sink(`[GIT] ${sanitizedMsg}`, data);
4445
+ } else {
4446
+ sink("[GIT]", data);
4447
+ }
4448
+ };
4449
+ var defaultLogger = {
4450
+ debug: tag(console.log),
4451
+ warn: tag(console.warn)
4452
+ };
4434
4453
 
4435
4454
  // src/utils/index.ts
4436
4455
  var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
@@ -7222,7 +7241,8 @@ var GQLClient = class {
7222
7241
  repoUrl,
7223
7242
  reference,
7224
7243
  sha,
7225
- shouldScan
7244
+ shouldScan,
7245
+ baselineCommit
7226
7246
  }) {
7227
7247
  const res = await this._clientSdk.DigestVulnerabilityReport({
7228
7248
  fixReportId,
@@ -7231,7 +7251,8 @@ var GQLClient = class {
7231
7251
  scanSource,
7232
7252
  repoUrl,
7233
7253
  reference,
7234
- sha
7254
+ sha,
7255
+ baselineCommit
7235
7256
  });
7236
7257
  if (res.digestVulnerabilityReport.__typename !== "VulnerabilityReport") {
7237
7258
  throw new Error("Digesting vulnerability report failed");
@@ -8148,7 +8169,7 @@ function getStableComputerName() {
8148
8169
  }
8149
8170
 
8150
8171
  // src/args/commands/upload_ai_blame.ts
8151
- var defaultLogger = {
8172
+ var defaultLogger2 = {
8152
8173
  info: (msg, data) => {
8153
8174
  if (data !== void 0) {
8154
8175
  console.log(msg, data);
@@ -8365,7 +8386,7 @@ async function uploadAiBlameHandler(options) {
8365
8386
  exitOnError = true,
8366
8387
  apiUrl,
8367
8388
  webAppUrl,
8368
- logger = defaultLogger
8389
+ logger = defaultLogger2
8369
8390
  } = options;
8370
8391
  const prompts = args.prompt || [];
8371
8392
  const inferences = args.inference || [];
package/dist/index.mjs CHANGED
@@ -1037,7 +1037,7 @@ var init_client_generates = __esm({
1037
1037
  }
1038
1038
  `;
1039
1039
  DigestVulnerabilityReportDocument = `
1040
- mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String) {
1040
+ mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String, $baselineCommit: String) {
1041
1041
  digestVulnerabilityReport(
1042
1042
  fixReportId: $fixReportId
1043
1043
  vulnerabilityReportFileName: $vulnerabilityReportFileName
@@ -1046,6 +1046,7 @@ var init_client_generates = __esm({
1046
1046
  repoUrl: $repoUrl
1047
1047
  reference: $reference
1048
1048
  sha: $sha
1049
+ baselineCommit: $baselineCommit
1049
1050
  ) {
1050
1051
  __typename
1051
1052
  ... on VulnerabilityReport {
@@ -1262,14 +1263,14 @@ var init_client_generates = __esm({
1262
1263
  GetLatestReportByRepoUrlDocument = `
1263
1264
  query GetLatestReportByRepoUrl($repoUrl: String!, $filters: fix_bool_exp = {}, $limit: Int!, $offset: Int!, $currentUserEmail: String!) {
1264
1265
  fixReport(
1265
- where: {_and: [{repo: {originalUrl: {_eq: $repoUrl}}}, {state: {_eq: Finished}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1266
+ where: {_and: [{repo: {originalUrl: {_ilike: $repoUrl}}}, {state: {_eq: Finished}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1266
1267
  order_by: {createdOn: desc}
1267
1268
  limit: 1
1268
1269
  ) {
1269
1270
  ...FixReportSummaryFields
1270
1271
  }
1271
1272
  expiredReport: fixReport(
1272
- where: {_and: [{repo: {originalUrl: {_eq: $repoUrl}}}, {state: {_eq: Expired}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1273
+ where: {_and: [{repo: {originalUrl: {_ilike: $repoUrl}}}, {state: {_eq: Expired}}, {vulnerabilityReport: {scanSource: {_neq: MCP}}}]}
1273
1274
  order_by: {createdOn: desc}
1274
1275
  limit: 1
1275
1276
  ) {
@@ -1364,8 +1365,8 @@ var init_client_generates = __esm({
1364
1365
 
1365
1366
  // src/features/analysis/scm/shared/src/getIssueType.ts
1366
1367
  import { z } from "zod";
1367
- function getTagTooltip(tag) {
1368
- switch (tag) {
1368
+ function getTagTooltip(tag2) {
1369
+ switch (tag2) {
1369
1370
  case "FALSE_POSITIVE":
1370
1371
  return "Issue was found to be a false positive";
1371
1372
  case "TEST_CODE":
@@ -1381,7 +1382,7 @@ function getTagTooltip(tag) {
1381
1382
  case "SUPPRESSED":
1382
1383
  return "Suppressed in the scan report";
1383
1384
  default:
1384
- return tag;
1385
+ return tag2;
1385
1386
  }
1386
1387
  }
1387
1388
  function replaceKeysWithValues(fixDescription, extraContext) {
@@ -1799,7 +1800,7 @@ var init_analysis = __esm({
1799
1800
 
1800
1801
  // src/features/analysis/scm/shared/src/types/issue.ts
1801
1802
  import { z as z9 } from "zod";
1802
- var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapCategoryToBucket, mapBucketTypeToCategory;
1803
+ var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, UnfixablePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapCategoryToBucket, mapBucketTypeToCategory;
1803
1804
  var init_issue = __esm({
1804
1805
  "src/features/analysis/scm/shared/src/types/issue.ts"() {
1805
1806
  "use strict";
@@ -1881,12 +1882,17 @@ var init_issue = __esm({
1881
1882
  return { codeDiff };
1882
1883
  })
1883
1884
  }).nullish(),
1884
- sharedState: VulnerabilityReportIssueSharedStateZ
1885
+ sharedState: VulnerabilityReportIssueSharedStateZ,
1886
+ unfixableId: z9.string().uuid().nullish()
1885
1887
  });
1886
1888
  FalsePositivePartsZ = z9.object({
1887
1889
  extraContext: z9.array(z9.object({ key: z9.string(), value: z9.string() })),
1888
1890
  fixDescription: z9.string()
1889
1891
  });
1892
+ UnfixablePartsZ = z9.object({
1893
+ extraContext: z9.array(z9.object({ key: z9.string(), value: z9.string() })),
1894
+ fixDescription: z9.string()
1895
+ });
1890
1896
  IssuePartsWithFixZ = BaseIssuePartsZ.merge(
1891
1897
  z9.object({
1892
1898
  category: z9.literal("Irrelevant" /* Irrelevant */),
@@ -1908,7 +1914,8 @@ var init_issue = __esm({
1908
1914
  z9.literal("Fixable" /* Fixable */),
1909
1915
  z9.literal("Filtered" /* Filtered */),
1910
1916
  z9.literal("Pending" /* Pending */)
1911
- ])
1917
+ ]),
1918
+ getUnfixable: UnfixablePartsZ.nullish()
1912
1919
  })
1913
1920
  );
1914
1921
  IssuePartsZ = z9.union([
@@ -4871,7 +4878,8 @@ var getCommitIssueDescription = ({
4871
4878
  vendor,
4872
4879
  issueType,
4873
4880
  irrelevantIssueWithTags,
4874
- fpDescription
4881
+ fpDescription,
4882
+ unfixableDescription
4875
4883
  }) => {
4876
4884
  const issueTypeString = getIssueTypeFriendlyString(issueType);
4877
4885
  let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
@@ -4887,7 +4895,7 @@ var getCommitIssueDescription = ({
4887
4895
 
4888
4896
 
4889
4897
  ## Justification
4890
- ${fpDescription ?? issueDescription[irrelevantIssueWithTags[0].tag]}
4898
+ ${fpDescription ?? unfixableDescription ?? issueDescription[irrelevantIssueWithTags[0].tag]}
4891
4899
  `;
4892
4900
  }
4893
4901
  const staticData = fixDetailsData[parseIssueTypeRes.data];
@@ -6909,25 +6917,18 @@ function getScmConfig({
6909
6917
  });
6910
6918
  const virtualDomain = filteredBrokerHosts[0]?.virtualDomain;
6911
6919
  const virtualUrl = virtualDomain ? `https://${virtualDomain}${urlObject.pathname}${urlObject.search}` : void 0;
6912
- const scmOrgConfig = filteredScmConfigs.find((scm) => scm.orgId && scm.token);
6913
- if (scmOrgConfig && includeOrgTokens) {
6914
- return {
6915
- id: scmOrgConfig.id,
6916
- accessToken: scmOrgConfig.token || void 0,
6917
- scmLibType: getScmLibTypeFromScmType(scmOrgConfig.scmType),
6918
- scmOrg: scmOrgConfig.scmOrg || void 0,
6919
- virtualUrl
6920
- };
6921
- }
6922
- const scmUserConfig = filteredScmConfigs.find(
6923
- (scm) => scm.userId && scm.token
6924
- );
6925
- if (scmUserConfig) {
6920
+ const matched = filteredScmConfigs.find((scm) => {
6921
+ if (!scm.token) return false;
6922
+ if (scm.userId) return true;
6923
+ if (scm.orgId) return includeOrgTokens;
6924
+ return false;
6925
+ });
6926
+ if (matched) {
6926
6927
  return {
6927
- id: scmUserConfig.id,
6928
- accessToken: scmUserConfig.token || void 0,
6929
- scmLibType: getScmLibTypeFromScmType(scmUserConfig.scmType),
6930
- scmOrg: scmUserConfig.scmOrg || void 0,
6928
+ id: matched.id,
6929
+ accessToken: matched.token || void 0,
6930
+ scmLibType: getScmLibTypeFromScmType(matched.scmType),
6931
+ scmOrg: matched.scmOrg || void 0,
6931
6932
  virtualUrl
6932
6933
  };
6933
6934
  }
@@ -9631,12 +9632,12 @@ function getGithubSdk(params = {}) {
9631
9632
  });
9632
9633
  },
9633
9634
  async getTagDate({
9634
- tag,
9635
+ tag: tag2,
9635
9636
  owner,
9636
9637
  repo
9637
9638
  }) {
9638
9639
  const refResponse = await octokit.rest.git.getRef({
9639
- ref: `tags/${tag}`,
9640
+ ref: `tags/${tag2}`,
9640
9641
  owner,
9641
9642
  repo
9642
9643
  });
@@ -10655,7 +10656,11 @@ var GithubSCMLib = class extends SCMLib {
10655
10656
  }
10656
10657
  const aDate = a.repoUpdatedAt ? Date.parse(a.repoUpdatedAt) : 0;
10657
10658
  const bDate = b.repoUpdatedAt ? Date.parse(b.repoUpdatedAt) : 0;
10658
- return (aDate - bDate) * sortOrder;
10659
+ const dateCmp = (aDate - bDate) * sortOrder;
10660
+ if (dateCmp !== 0) {
10661
+ return dateCmp;
10662
+ }
10663
+ return a.repoName.localeCompare(b.repoName) * sortOrder;
10659
10664
  });
10660
10665
  const limit = params.limit || 10;
10661
10666
  const offset = parseCursorSafe(params.cursor, 0);
@@ -12268,22 +12273,24 @@ if (!semver.satisfies(process.version, packageJson.engines.node)) {
12268
12273
 
12269
12274
  // src/utils/gitUtils.ts
12270
12275
  import simpleGit2 from "simple-git";
12271
- var defaultLogger = {
12272
- info: (data, msg) => {
12273
- if (msg) {
12274
- const sanitizedMsg = String(msg).replace(/\n|\r/g, "");
12275
- console.log(`[GIT] ${sanitizedMsg}`, data);
12276
- } else {
12277
- console.log("[GIT]", data);
12278
- }
12276
+ var tag = (sink) => (data, msg) => {
12277
+ if (msg) {
12278
+ const sanitizedMsg = String(msg).replace(/\n|\r/g, "");
12279
+ sink(`[GIT] ${sanitizedMsg}`, data);
12280
+ } else {
12281
+ sink("[GIT]", data);
12279
12282
  }
12280
12283
  };
12284
+ var defaultLogger = {
12285
+ debug: tag(console.log),
12286
+ warn: tag(console.warn)
12287
+ };
12281
12288
  function createGitWithLogging(dirName, logger3 = defaultLogger) {
12282
12289
  return simpleGit2(dirName, {
12283
12290
  maxConcurrentProcesses: 6
12284
12291
  }).outputHandler((bin, stdout2, stderr2) => {
12285
12292
  const callID = Math.random();
12286
- logger3.info({ callID, bin }, "Start git CLI call");
12293
+ logger3.debug({ callID, bin }, "Start git CLI call");
12287
12294
  let errChunks = [];
12288
12295
  let outChunks = [];
12289
12296
  let isStdoutDone = false;
@@ -12304,7 +12311,7 @@ function createGitWithLogging(dirName, logger3 = defaultLogger) {
12304
12311
  err: `${errChunks.join("").slice(0, 200)}...`,
12305
12312
  out: `${outChunks.join("").slice(0, 200)}...`
12306
12313
  };
12307
- logger3.info(logObj, "git log output");
12314
+ logger3.debug(logObj, "git log output");
12308
12315
  stderr2.removeListener("data", onStderrData);
12309
12316
  stdout2.removeListener("data", onStdoutData);
12310
12317
  errChunks = [];
@@ -12318,11 +12325,11 @@ function createGitWithLogging(dirName, logger3 = defaultLogger) {
12318
12325
  stderr2.on("close", () => markDone("stderr"));
12319
12326
  stdout2.on("close", () => markDone("stdout"));
12320
12327
  stderr2.on("error", (error) => {
12321
- logger3.info({ callID, error: String(error) }, "git stderr stream error");
12328
+ logger3.warn({ callID, error: String(error) }, "git stderr stream error");
12322
12329
  markDone("stderr");
12323
12330
  });
12324
12331
  stdout2.on("error", (error) => {
12325
- logger3.info({ callID, error: String(error) }, "git stdout stream error");
12332
+ logger3.warn({ callID, error: String(error) }, "git stdout stream error");
12326
12333
  markDone("stdout");
12327
12334
  });
12328
12335
  });
@@ -12340,15 +12347,15 @@ import sax from "sax";
12340
12347
  var BaseStreamParser = class {
12341
12348
  constructor(parser) {
12342
12349
  __publicField(this, "currentPath", []);
12343
- parser.on("opentag", (tag) => this.onOpenTag(tag));
12350
+ parser.on("opentag", (tag2) => this.onOpenTag(tag2));
12344
12351
  parser.on("closetag", () => this.onCloseTag());
12345
12352
  parser.on("text", (text) => this.onText(text));
12346
12353
  }
12347
12354
  getPathString() {
12348
12355
  return this.currentPath.join(" > ");
12349
12356
  }
12350
- onOpenTag(tag) {
12351
- this.currentPath.push(tag.name);
12357
+ onOpenTag(tag2) {
12358
+ this.currentPath.push(tag2.name);
12352
12359
  }
12353
12360
  onCloseTag() {
12354
12361
  this.currentPath.pop();
@@ -12361,12 +12368,12 @@ var AuditMetadataParser = class extends BaseStreamParser {
12361
12368
  super(...arguments);
12362
12369
  __publicField(this, "suppressedMap", {});
12363
12370
  }
12364
- onOpenTag(tag) {
12365
- super.onOpenTag(tag);
12371
+ onOpenTag(tag2) {
12372
+ super.onOpenTag(tag2);
12366
12373
  switch (this.getPathString()) {
12367
12374
  case "Audit > IssueList > Issue":
12368
- this.suppressedMap[String(tag.attributes["instanceId"] ?? "")] = String(
12369
- tag.attributes["suppressed"] ?? ""
12375
+ this.suppressedMap[String(tag2.attributes["instanceId"] ?? "")] = String(
12376
+ tag2.attributes["suppressed"] ?? ""
12370
12377
  );
12371
12378
  break;
12372
12379
  }
@@ -12385,18 +12392,18 @@ var ReportMetadataParser = class extends BaseStreamParser {
12385
12392
  __publicField(this, "ruleId", "");
12386
12393
  __publicField(this, "groupName", "");
12387
12394
  }
12388
- onOpenTag(tag) {
12389
- super.onOpenTag(tag);
12395
+ onOpenTag(tag2) {
12396
+ super.onOpenTag(tag2);
12390
12397
  switch (this.getPathString()) {
12391
12398
  case "FVDL > EngineData > RuleInfo > Rule":
12392
- this.ruleId = String(tag.attributes["id"] ?? "");
12399
+ this.ruleId = String(tag2.attributes["id"] ?? "");
12393
12400
  break;
12394
12401
  case "FVDL > EngineData > RuleInfo > Rule > MetaInfo > Group":
12395
- this.groupName = String(tag.attributes["name"] ?? "");
12402
+ this.groupName = String(tag2.attributes["name"] ?? "");
12396
12403
  break;
12397
12404
  case "FVDL > CreatedTS":
12398
- this.createdTSDate = String(tag.attributes["date"] ?? "");
12399
- this.createdTSTime = String(tag.attributes["time"] ?? "");
12405
+ this.createdTSDate = String(tag2.attributes["date"] ?? "");
12406
+ this.createdTSTime = String(tag2.attributes["time"] ?? "");
12400
12407
  break;
12401
12408
  }
12402
12409
  }
@@ -12429,19 +12436,19 @@ var UnifiedNodePoolParser = class extends BaseStreamParser {
12429
12436
  __publicField(this, "codePoints", {});
12430
12437
  __publicField(this, "nodeId", "");
12431
12438
  }
12432
- onOpenTag(tag) {
12433
- super.onOpenTag(tag);
12439
+ onOpenTag(tag2) {
12440
+ super.onOpenTag(tag2);
12434
12441
  switch (this.getPathString()) {
12435
12442
  case "FVDL > UnifiedNodePool > Node":
12436
- this.nodeId = String(tag.attributes["id"] ?? "");
12443
+ this.nodeId = String(tag2.attributes["id"] ?? "");
12437
12444
  break;
12438
12445
  case "FVDL > UnifiedNodePool > Node > SourceLocation":
12439
12446
  this.codePoints[this.nodeId] = {
12440
- path: String(tag.attributes["path"] ?? ""),
12441
- colStart: String(tag.attributes["colStart"] ?? ""),
12442
- colEnd: String(tag.attributes["colEnd"] ?? ""),
12443
- line: String(tag.attributes["line"] ?? ""),
12444
- lineEnd: String(tag.attributes["lineEnd"] ?? "")
12447
+ path: String(tag2.attributes["path"] ?? ""),
12448
+ colStart: String(tag2.attributes["colStart"] ?? ""),
12449
+ colEnd: String(tag2.attributes["colEnd"] ?? ""),
12450
+ line: String(tag2.attributes["line"] ?? ""),
12451
+ lineEnd: String(tag2.attributes["lineEnd"] ?? "")
12445
12452
  };
12446
12453
  break;
12447
12454
  }
@@ -12463,8 +12470,8 @@ var VulnerabilityParser = class extends BaseStreamParser {
12463
12470
  this.tmpStorageFilePath = tmpStorageFilePath;
12464
12471
  this.tmpStorageFileWriter = fs5.createWriteStream(tmpStorageFilePath);
12465
12472
  }
12466
- onOpenTag(tag) {
12467
- super.onOpenTag(tag);
12473
+ onOpenTag(tag2) {
12474
+ super.onOpenTag(tag2);
12468
12475
  switch (this.getPathString()) {
12469
12476
  case "FVDL > Vulnerabilities > Vulnerability":
12470
12477
  this.isInVulnerability = true;
@@ -12473,21 +12480,21 @@ var VulnerabilityParser = class extends BaseStreamParser {
12473
12480
  this.codePoints = [];
12474
12481
  break;
12475
12482
  case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > MetaInfo > Group":
12476
- this.groupName = String(tag.attributes["name"] ?? "");
12483
+ this.groupName = String(tag2.attributes["name"] ?? "");
12477
12484
  break;
12478
12485
  }
12479
12486
  if (this.isInVulnerability) {
12480
12487
  if (this.getPathString().endsWith(" > Entry > Node > SourceLocation")) {
12481
12488
  this.codePoints.push({
12482
- path: String(tag.attributes["path"] ?? ""),
12483
- colStart: String(tag.attributes["colStart"] ?? ""),
12484
- colEnd: String(tag.attributes["colEnd"] ?? ""),
12485
- line: String(tag.attributes["line"] ?? ""),
12486
- lineEnd: String(tag.attributes["lineEnd"] ?? "")
12489
+ path: String(tag2.attributes["path"] ?? ""),
12490
+ colStart: String(tag2.attributes["colStart"] ?? ""),
12491
+ colEnd: String(tag2.attributes["colEnd"] ?? ""),
12492
+ line: String(tag2.attributes["line"] ?? ""),
12493
+ lineEnd: String(tag2.attributes["lineEnd"] ?? "")
12487
12494
  });
12488
12495
  } else if (this.getPathString().endsWith(" > Entry > NodeRef")) {
12489
12496
  this.codePoints.push({
12490
- id: String(tag.attributes["id"] ?? "")
12497
+ id: String(tag2.attributes["id"] ?? "")
12491
12498
  });
12492
12499
  }
12493
12500
  }
@@ -12964,6 +12971,12 @@ var convertToSarifCodePathPatternsOption = {
12964
12971
  type: "string",
12965
12972
  array: true
12966
12973
  };
12974
+ var baselineCommitOption = {
12975
+ describe: chalk2.bold(
12976
+ "Only report findings introduced since this commit (PR mode). The sha must be reachable from the scanned repository \u2014 unreachable baselines fail the scan loudly. Effective only when no scan file is provided."
12977
+ ),
12978
+ type: "string"
12979
+ };
12967
12980
  var pollingOption = {
12968
12981
  describe: chalk2.bold(
12969
12982
  "Use HTTP polling instead of WebSocket for status updates. Useful for proxy environments or firewalls that block WebSocket connections. Polling interval: 5 seconds, timeout: 30 minutes."
@@ -13615,7 +13628,8 @@ var GQLClient = class {
13615
13628
  repoUrl,
13616
13629
  reference,
13617
13630
  sha,
13618
- shouldScan
13631
+ shouldScan,
13632
+ baselineCommit
13619
13633
  }) {
13620
13634
  const res = await this._clientSdk.DigestVulnerabilityReport({
13621
13635
  fixReportId,
@@ -13624,7 +13638,8 @@ var GQLClient = class {
13624
13638
  scanSource,
13625
13639
  repoUrl,
13626
13640
  reference,
13627
- sha
13641
+ sha,
13642
+ baselineCommit
13628
13643
  });
13629
13644
  if (res.digestVulnerabilityReport.__typename !== "VulnerabilityReport") {
13630
13645
  throw new Error("Digesting vulnerability report failed");
@@ -16038,10 +16053,10 @@ function createFork({ args, processPath, name }, options) {
16038
16053
  });
16039
16054
  return createChildProcess({ childProcess: child, name }, options);
16040
16055
  }
16041
- function createSpawn({ args, processPath, name, cwd }, options) {
16056
+ function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
16042
16057
  const child = cp.spawn(processPath, args, {
16043
16058
  stdio: ["inherit", "pipe", "pipe", "ipc"],
16044
- env: { ...process2.env },
16059
+ env: { ...process2.env, ...env3 },
16045
16060
  cwd
16046
16061
  });
16047
16062
  return createChildProcess({ childProcess: child, name }, options);
@@ -16496,7 +16511,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16496
16511
  createOnePr,
16497
16512
  commitDirectly,
16498
16513
  pullRequest,
16499
- polling
16514
+ polling,
16515
+ baselineCommit
16500
16516
  } = params;
16501
16517
  debug21("start %s %s", dirname, repo);
16502
16518
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
@@ -16613,7 +16629,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
16613
16629
  sha,
16614
16630
  reference,
16615
16631
  shouldScan,
16616
- polling
16632
+ polling,
16633
+ // Only meaningful when opengrep is going to run (no user-supplied report).
16634
+ baselineCommit: shouldScan ? baselineCommit : void 0
16617
16635
  });
16618
16636
  uploadReportSpinner.success({ text: "\u{1F4C1} Report uploaded successfully" });
16619
16637
  const mobbSpinner = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
@@ -16756,7 +16774,11 @@ async function _scan(params, { skipPrompts = false } = {}) {
16756
16774
  command,
16757
16775
  ci,
16758
16776
  shouldScan: shouldScan2,
16759
- polling
16777
+ polling,
16778
+ // shouldScan is false here (user provided a report); baseline filter
16779
+ // only applies to the opengrep code path. Drop it to keep the contract
16780
+ // honest with the CLI help text.
16781
+ baselineCommit: void 0
16760
16782
  });
16761
16783
  const res = await _zipAndUploadRepo({
16762
16784
  srcPath,
@@ -16780,7 +16802,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
16780
16802
  command,
16781
16803
  ci,
16782
16804
  shouldScan: shouldScan2,
16783
- polling
16805
+ polling,
16806
+ baselineCommit
16784
16807
  });
16785
16808
  }
16786
16809
  const mobbSpinner2 = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
@@ -16875,7 +16898,8 @@ async function _digestReport({
16875
16898
  sha,
16876
16899
  reference,
16877
16900
  shouldScan,
16878
- polling
16901
+ polling,
16902
+ baselineCommit
16879
16903
  }) {
16880
16904
  const digestSpinner = createSpinner4(
16881
16905
  progressMassages.processingVulnerabilityReport
@@ -16889,7 +16913,8 @@ async function _digestReport({
16889
16913
  repoUrl,
16890
16914
  sha,
16891
16915
  reference,
16892
- shouldScan
16916
+ shouldScan,
16917
+ baselineCommit
16893
16918
  }
16894
16919
  );
16895
16920
  const callbackStates = [
@@ -17139,7 +17164,8 @@ async function analyze({
17139
17164
  createOnePr,
17140
17165
  commitDirectly,
17141
17166
  pullRequest,
17142
- polling
17167
+ polling,
17168
+ baselineCommit
17143
17169
  }, { skipPrompts = false } = {}) {
17144
17170
  !ci && await showWelcomeMessage(skipPrompts);
17145
17171
  await runAnalysis(
@@ -17158,7 +17184,8 @@ async function analyze({
17158
17184
  commitDirectly,
17159
17185
  pullRequest,
17160
17186
  createOnePr,
17161
- polling
17187
+ polling,
17188
+ baselineCommit
17162
17189
  },
17163
17190
  { skipPrompts }
17164
17191
  );
@@ -17368,9 +17395,12 @@ function analyzeBuilder(yargs2) {
17368
17395
  describe: chalk10.bold("Number of the pull request"),
17369
17396
  type: "number",
17370
17397
  demandOption: false
17371
- }).option("polling", pollingOption).example(
17398
+ }).option("polling", pollingOption).option("baseline-commit", baselineCommitOption).example(
17372
17399
  "npx mobbdev@latest analyze -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path>",
17373
17400
  "analyze an existing repository"
17401
+ ).example(
17402
+ "npx mobbdev@latest analyze -r https://github.com/org/repo --baseline-commit <sha>",
17403
+ "analyze only findings introduced since <sha> (PR-mode scan)"
17374
17404
  ).help();
17375
17405
  }
17376
17406
  function validateAnalyzeOptions(argv) {
@@ -19369,7 +19399,7 @@ function createLogger(config2) {
19369
19399
 
19370
19400
  // src/features/claude_code/hook_logger.ts
19371
19401
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
19372
- var CLI_VERSION = true ? "1.4.12" : "unknown";
19402
+ var CLI_VERSION = true ? "1.4.15" : "unknown";
19373
19403
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
19374
19404
  var claudeCodeVersion;
19375
19405
  function buildDdTags() {
@@ -21435,8 +21465,9 @@ var McpGQLClient = class extends GQLClient {
21435
21465
  codeNodes: { path: { _in: fileFilter } }
21436
21466
  };
21437
21467
  }
21468
+ const escapedRepoUrl = repoUrl.replace(/[%_\\]/g, (c) => `\\${c}`);
21438
21469
  const resp = await this._clientSdk.GetLatestReportByRepoUrl({
21439
- repoUrl,
21470
+ repoUrl: escapedRepoUrl,
21440
21471
  limit,
21441
21472
  offset,
21442
21473
  currentUserEmail,
@@ -25920,7 +25951,7 @@ var LocalMobbFolderService = class {
25920
25951
  if (fix.vulnerabilityReportIssues.length > 0) {
25921
25952
  fix.vulnerabilityReportIssues.forEach((issue) => {
25922
25953
  if (issue.vulnerabilityReportIssueTags && issue.vulnerabilityReportIssueTags.length > 0) {
25923
- markdown += `**Tags:** ${issue.vulnerabilityReportIssueTags.map((tag) => tag.vulnerability_report_issue_tag_value).join(", ")}
25954
+ markdown += `**Tags:** ${issue.vulnerabilityReportIssueTags.map((tag2) => tag2.vulnerability_report_issue_tag_value).join(", ")}
25924
25955
 
25925
25956
  `;
25926
25957
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.4.12",
3
+ "version": "1.4.15",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",
@@ -17,10 +17,12 @@
17
17
  "test:mcp:watch": "vitest watch __tests__/mcp/",
18
18
  "test:mcp:verbose": "pnpm run build && NODE_ENV=test VERBOSE=true vitest run __tests__/mcp/",
19
19
  "test:mcp:all": "pnpm run test:unit:mcp && pnpm run test:integration:mcp && pnpm run test:e2e:mcp",
20
- "test:unit": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --exclude='**/__tests__/integration.test.ts' --exclude='**/__tests__/integration.mcp.test.ts' --exclude='**/__tests__/mcp/**'",
21
- "test:unit:ci": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --bail=1 --exclude='**/__tests__/integration.test.ts' --exclude='**/__tests__/integration.mcp.test.ts' --exclude='**/__tests__/mcp/**'",
20
+ "test:unit": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --exclude='**/__tests__/integration.test.ts' --exclude='**/__tests__/integration.mcp.test.ts' --exclude='**/__tests__/integration.baseline-commit.test.ts' --exclude='**/__tests__/mcp/**'",
21
+ "test:unit:ci": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --bail=1 --exclude='**/__tests__/integration.test.ts' --exclude='**/__tests__/integration.mcp.test.ts' --exclude='**/__tests__/integration.baseline-commit.test.ts' --exclude='**/__tests__/mcp/**'",
22
22
  "test:integration": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --sequence.concurrent=false false __tests__/integration.test.ts",
23
23
  "test:integration:ci": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --bail=1 --sequence.concurrent=false false __tests__/integration.test.ts",
24
+ "test:integration:baseline-commit": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --sequence.concurrent=false false __tests__/integration.baseline-commit.test.ts",
25
+ "test:integration:baseline-commit:proxy": "GIT_PROXY_HOST=http://tinyproxy:8888 HTTP_PROXY=http://localhost:8888 API_URL=http://app-api:8080/v1/graphql TOKEN=$(../../scripts/login_auth0.sh) vitest run --bail=1 --sequence.concurrent=false false __tests__/integration.baseline-commit.test.ts",
24
26
  "test:integration:mcp": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --sequence.concurrent=false false __tests__/integration.mcp.test.ts",
25
27
  "test:integration:mcp:ci": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest run --bail=1 --sequence.concurrent=false false __tests__/integration.mcp.test.ts",
26
28
  "test:integration:watch": "GIT_PROXY_HOST=http://tinyproxy:8888 TOKEN=$(../../scripts/login_auth0.sh) vitest watch run __tests__/integration.test.ts",
@@ -135,6 +137,7 @@
135
137
  "@typescript-eslint/parser": "7.17.0",
136
138
  "@vitest/coverage-v8": "3.2.4",
137
139
  "@vitest/ui": "3.2.4",
140
+ "dotenv-cli": "10.0.0",
138
141
  "eslint": "8.57.0",
139
142
  "eslint-plugin-graphql": "4.0.0",
140
143
  "eslint-plugin-import": "2.32.0",