mobbdev 1.0.77 → 1.0.81

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 (2) hide show
  1. package/dist/index.mjs +1136 -669
  2. package/package.json +4 -1
package/dist/index.mjs CHANGED
@@ -10,32 +10,253 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
10
10
  import Debug20 from "debug";
11
11
  import { hideBin } from "yargs/helpers";
12
12
 
13
- // src/types.ts
14
- var mobbCliCommand = {
15
- addScmToken: "add-scm-token",
16
- scan: "scan",
17
- analyze: "analyze",
18
- review: "review"
19
- };
13
+ // src/args/commands/convert_to_sarif.ts
14
+ import fs4 from "node:fs";
20
15
 
21
- // src/args/yargs.ts
22
- import chalk10 from "chalk";
23
- import yargs from "yargs/yargs";
16
+ // src/commands/convert_to_sarif.ts
17
+ import fs3 from "node:fs";
18
+ import path3 from "node:path";
24
19
 
25
- // src/args/commands/analyze.ts
26
- import fs4 from "node:fs";
20
+ // src/commands/fpr_stream_parser.ts
21
+ import fs from "node:fs";
22
+ import sax from "sax";
23
+ var BaseStreamParser = class {
24
+ constructor(parser) {
25
+ __publicField(this, "currentPath", []);
26
+ parser.on("opentag", (tag) => this.onOpenTag(tag));
27
+ parser.on("closetag", () => this.onCloseTag());
28
+ parser.on("text", (text) => this.onText(text));
29
+ }
30
+ getPathString() {
31
+ return this.currentPath.join(" > ");
32
+ }
33
+ onOpenTag(tag) {
34
+ this.currentPath.push(tag.name);
35
+ }
36
+ onCloseTag() {
37
+ this.currentPath.pop();
38
+ }
39
+ onText(_text) {
40
+ }
41
+ };
42
+ var AuditMetadataParser = class extends BaseStreamParser {
43
+ constructor() {
44
+ super(...arguments);
45
+ __publicField(this, "suppressedMap", {});
46
+ }
47
+ onOpenTag(tag) {
48
+ super.onOpenTag(tag);
49
+ switch (this.getPathString()) {
50
+ case "Audit > IssueList > Issue":
51
+ this.suppressedMap[String(tag.attributes["instanceId"] ?? "")] = String(
52
+ tag.attributes["suppressed"] ?? ""
53
+ );
54
+ break;
55
+ }
56
+ }
57
+ getAuditMetadata() {
58
+ return this.suppressedMap;
59
+ }
60
+ };
61
+ var ReportMetadataParser = class extends BaseStreamParser {
62
+ constructor() {
63
+ super(...arguments);
64
+ __publicField(this, "uuid", "");
65
+ __publicField(this, "createdTSDate", "");
66
+ __publicField(this, "createdTSTime", "");
67
+ __publicField(this, "rules", {});
68
+ __publicField(this, "ruleId", "");
69
+ __publicField(this, "groupName", "");
70
+ }
71
+ onOpenTag(tag) {
72
+ super.onOpenTag(tag);
73
+ switch (this.getPathString()) {
74
+ case "FVDL > EngineData > RuleInfo > Rule":
75
+ this.ruleId = String(tag.attributes["id"] ?? "");
76
+ break;
77
+ case "FVDL > EngineData > RuleInfo > Rule > MetaInfo > Group":
78
+ this.groupName = String(tag.attributes["name"] ?? "");
79
+ break;
80
+ case "FVDL > CreatedTS":
81
+ this.createdTSDate = String(tag.attributes["date"] ?? "");
82
+ this.createdTSTime = String(tag.attributes["time"] ?? "");
83
+ break;
84
+ }
85
+ }
86
+ onText(text) {
87
+ super.onText(text);
88
+ switch (this.getPathString()) {
89
+ case "FVDL > UUID":
90
+ this.uuid = text;
91
+ break;
92
+ case "FVDL > EngineData > RuleInfo > Rule > MetaInfo > Group": {
93
+ const ruleMeta = this.rules[this.ruleId] ?? {};
94
+ ruleMeta[this.groupName] = text;
95
+ this.rules[this.ruleId] = ruleMeta;
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ getReportMetadata() {
101
+ return {
102
+ createdTSDate: this.createdTSDate,
103
+ createdTSTime: this.createdTSTime,
104
+ uuid: this.uuid,
105
+ rules: this.rules
106
+ };
107
+ }
108
+ };
109
+ var UnifiedNodePoolParser = class extends BaseStreamParser {
110
+ constructor() {
111
+ super(...arguments);
112
+ __publicField(this, "codePoints", {});
113
+ __publicField(this, "nodeId", "");
114
+ }
115
+ onOpenTag(tag) {
116
+ super.onOpenTag(tag);
117
+ switch (this.getPathString()) {
118
+ case "FVDL > UnifiedNodePool > Node":
119
+ this.nodeId = String(tag.attributes["id"] ?? "");
120
+ break;
121
+ case "FVDL > UnifiedNodePool > Node > SourceLocation":
122
+ this.codePoints[this.nodeId] = {
123
+ path: String(tag.attributes["path"] ?? ""),
124
+ colStart: String(tag.attributes["colStart"] ?? ""),
125
+ colEnd: String(tag.attributes["colEnd"] ?? ""),
126
+ line: String(tag.attributes["line"] ?? ""),
127
+ lineEnd: String(tag.attributes["lineEnd"] ?? "")
128
+ };
129
+ break;
130
+ }
131
+ }
132
+ getNodesPull() {
133
+ return this.codePoints;
134
+ }
135
+ };
136
+ var VulnerabilityParser = class extends BaseStreamParser {
137
+ constructor() {
138
+ super(...arguments);
139
+ __publicField(this, "vulnerabilities", []);
140
+ __publicField(this, "isInVulnerability", false);
141
+ __publicField(this, "codePoints", []);
142
+ __publicField(this, "metadata", {});
143
+ __publicField(this, "metaInfo", {});
144
+ __publicField(this, "groupName", "");
145
+ }
146
+ onOpenTag(tag) {
147
+ super.onOpenTag(tag);
148
+ switch (this.getPathString()) {
149
+ case "FVDL > Vulnerabilities > Vulnerability":
150
+ this.isInVulnerability = true;
151
+ this.metadata = {};
152
+ this.metaInfo = {};
153
+ this.codePoints = [];
154
+ break;
155
+ case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > MetaInfo > Group":
156
+ this.groupName = String(tag.attributes["name"] ?? "");
157
+ break;
158
+ }
159
+ if (this.isInVulnerability) {
160
+ if (this.getPathString().endsWith(" > Entry > Node > SourceLocation")) {
161
+ this.codePoints.push({
162
+ path: String(tag.attributes["path"] ?? ""),
163
+ colStart: String(tag.attributes["colStart"] ?? ""),
164
+ colEnd: String(tag.attributes["colEnd"] ?? ""),
165
+ line: String(tag.attributes["line"] ?? ""),
166
+ lineEnd: String(tag.attributes["lineEnd"] ?? "")
167
+ });
168
+ } else if (this.getPathString().endsWith(" > Entry > NodeRef")) {
169
+ this.codePoints.push({
170
+ id: String(tag.attributes["id"] ?? "")
171
+ });
172
+ }
173
+ }
174
+ }
175
+ onText(text) {
176
+ super.onText(text);
177
+ const lastPathSegment = this.currentPath.at(-1);
178
+ if (!this.isInVulnerability || !lastPathSegment) {
179
+ return;
180
+ }
181
+ switch (this.getPathString()) {
182
+ case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > InstanceID":
183
+ case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > InstanceSeverity":
184
+ case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > Confidence":
185
+ case "FVDL > Vulnerabilities > Vulnerability > ClassInfo > ClassID":
186
+ case "FVDL > Vulnerabilities > Vulnerability > ClassInfo > Type":
187
+ case "FVDL > Vulnerabilities > Vulnerability > ClassInfo > Subtype":
188
+ this.metadata[lastPathSegment] = text;
189
+ break;
190
+ case "FVDL > Vulnerabilities > Vulnerability > InstanceInfo > MetaInfo > Group":
191
+ this.metaInfo[this.groupName] = text;
192
+ break;
193
+ }
194
+ }
195
+ onCloseTag() {
196
+ if (this.getPathString() === "FVDL > Vulnerabilities > Vulnerability") {
197
+ this.isInVulnerability = false;
198
+ this.vulnerabilities.push({
199
+ nodes: this.codePoints,
200
+ instanceID: this.metadata["InstanceID"] ?? "",
201
+ instanceSeverity: this.metadata["InstanceSeverity"] ?? "",
202
+ confidence: this.metadata["Confidence"] ?? "",
203
+ classID: this.metadata["ClassID"] ?? "",
204
+ type: this.metadata["Type"] ?? "",
205
+ subtype: this.metadata["Subtype"] ?? "",
206
+ metaInfo: this.metaInfo
207
+ });
208
+ }
209
+ super.onCloseTag();
210
+ }
211
+ getVulnerabilities() {
212
+ return this.vulnerabilities;
213
+ }
214
+ };
215
+ function initSaxParser(filepath) {
216
+ const parser = sax.createStream(true);
217
+ const awaiter = new Promise((resolve, reject) => {
218
+ parser.on("end", () => resolve(true));
219
+ parser.on("error", (e) => reject(e));
220
+ });
221
+ return {
222
+ parser,
223
+ parse: async () => {
224
+ fs.createReadStream(filepath).pipe(parser);
225
+ await awaiter;
226
+ }
227
+ };
228
+ }
27
229
 
28
- // src/commands/index.ts
29
- import crypto from "node:crypto";
30
- import os from "node:os";
230
+ // src/features/analysis/scm/errors.ts
231
+ var InvalidRepoUrlError = class extends Error {
232
+ constructor(m) {
233
+ super(m);
234
+ }
235
+ };
236
+ var InvalidAccessTokenError = class extends Error {
237
+ constructor(m) {
238
+ super(m);
239
+ }
240
+ };
241
+ var InvalidUrlPatternError = class extends Error {
242
+ constructor(m) {
243
+ super(m);
244
+ }
245
+ };
246
+ var RefNotFoundError = class extends Error {
247
+ constructor(m) {
248
+ super(m);
249
+ }
250
+ };
251
+ var RepoNoTokenAccessError = class extends Error {
252
+ constructor(m, scmType) {
253
+ super(m);
254
+ this.scmType = scmType;
255
+ }
256
+ };
31
257
 
32
- // src/constants.ts
33
- import path from "node:path";
34
- import { fileURLToPath } from "node:url";
35
- import chalk from "chalk";
36
- import Debug from "debug";
37
- import * as dotenv from "dotenv";
38
- import { z as z8 } from "zod";
258
+ // src/features/analysis/scm/shared/src/types/fix.ts
259
+ import { z as z2 } from "zod";
39
260
 
40
261
  // src/features/analysis/scm/generates/client_generates.ts
41
262
  var FixQuestionInputType = /* @__PURE__ */ ((FixQuestionInputType2) => {
@@ -111,6 +332,7 @@ var IssueLanguage_Enum = /* @__PURE__ */ ((IssueLanguage_Enum2) => {
111
332
  })(IssueLanguage_Enum || {});
112
333
  var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
113
334
  IssueType_Enum2["AutoEscapeFalse"] = "AUTO_ESCAPE_FALSE";
335
+ IssueType_Enum2["AvoidBuiltinShadowing"] = "AVOID_BUILTIN_SHADOWING";
114
336
  IssueType_Enum2["AvoidIdentityComparisonCachedTypes"] = "AVOID_IDENTITY_COMPARISON_CACHED_TYPES";
115
337
  IssueType_Enum2["ClientDomStoredCodeInjection"] = "CLIENT_DOM_STORED_CODE_INJECTION";
116
338
  IssueType_Enum2["CmDi"] = "CMDi";
@@ -140,6 +362,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
140
362
  IssueType_Enum2["IframeWithoutSandbox"] = "IFRAME_WITHOUT_SANDBOX";
141
363
  IssueType_Enum2["ImproperExceptionHandling"] = "IMPROPER_EXCEPTION_HANDLING";
142
364
  IssueType_Enum2["ImproperResourceShutdownOrRelease"] = "IMPROPER_RESOURCE_SHUTDOWN_OR_RELEASE";
365
+ IssueType_Enum2["ImproperStringFormatting"] = "IMPROPER_STRING_FORMATTING";
143
366
  IssueType_Enum2["IncompleteHostnameRegex"] = "INCOMPLETE_HOSTNAME_REGEX";
144
367
  IssueType_Enum2["IncompleteUrlSanitization"] = "INCOMPLETE_URL_SANITIZATION";
145
368
  IssueType_Enum2["IncompleteUrlSchemeCheck"] = "INCOMPLETE_URL_SCHEME_CHECK";
@@ -203,6 +426,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
203
426
  IssueType_Enum2["WeakEncryption"] = "WEAK_ENCRYPTION";
204
427
  IssueType_Enum2["WeakXmlSchemaUnboundedOccurrences"] = "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES";
205
428
  IssueType_Enum2["WebsocketMissingOriginCheck"] = "WEBSOCKET_MISSING_ORIGIN_CHECK";
429
+ IssueType_Enum2["WildcardImports"] = "WILDCARD_IMPORTS";
206
430
  IssueType_Enum2["Xss"] = "XSS";
207
431
  IssueType_Enum2["Xxe"] = "XXE";
208
432
  IssueType_Enum2["ZipSlip"] = "ZIP_SLIP";
@@ -246,6 +470,7 @@ var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Ve
246
470
  Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
247
471
  Vulnerability_Report_Vendor_Enum3["Datadog"] = "datadog";
248
472
  Vulnerability_Report_Vendor_Enum3["Fortify"] = "fortify";
473
+ Vulnerability_Report_Vendor_Enum3["FortifyMobbSarif"] = "fortifyMobbSarif";
249
474
  Vulnerability_Report_Vendor_Enum3["Opengrep"] = "opengrep";
250
475
  Vulnerability_Report_Vendor_Enum3["Semgrep"] = "semgrep";
251
476
  Vulnerability_Report_Vendor_Enum3["Snyk"] = "snyk";
@@ -753,9 +978,6 @@ function getSdk(client, withWrapper = defaultWrapper) {
753
978
  };
754
979
  }
755
980
 
756
- // src/features/analysis/scm/shared/src/types/fix.ts
757
- import { z as z2 } from "zod";
758
-
759
981
  // src/features/analysis/scm/shared/src/types/shared.ts
760
982
  import { z } from "zod";
761
983
  var ParsedSeverityZ = z.nativeEnum(Vulnerability_Severity_Enum).nullish().transform((i) => i ?? "low" /* Low */);
@@ -1177,7 +1399,10 @@ var issueTypeMap = {
1177
1399
  ["RETURN_SHOULD_NOT_BE_INVARIANT" /* ReturnShouldNotBeInvariant */]: "Return Should Not Be Invariant",
1178
1400
  ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: "SystemExit Should Reraise",
1179
1401
  ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: "No Return in Finally Block",
1180
- ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types"
1402
+ ["WILDCARD_IMPORTS" /* WildcardImports */]: "Wildcard Imports should not be used",
1403
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types",
1404
+ ["AVOID_BUILTIN_SHADOWING" /* AvoidBuiltinShadowing */]: "Avoid Builtin Shadowing",
1405
+ ["IMPROPER_STRING_FORMATTING" /* ImproperStringFormatting */]: "Improper String Formatting"
1181
1406
  };
1182
1407
  var issueTypeZ = z5.nativeEnum(IssueType_Enum);
1183
1408
  var getIssueTypeFriendlyString = (issueType) => {
@@ -1630,290 +1855,49 @@ var ScmType = /* @__PURE__ */ ((ScmType2) => {
1630
1855
  ScmType2["Bitbucket"] = "Bitbucket";
1631
1856
  return ScmType2;
1632
1857
  })(ScmType || {});
1858
+ var ConvertToSarifInputFileFormat = /* @__PURE__ */ ((ConvertToSarifInputFileFormat2) => {
1859
+ ConvertToSarifInputFileFormat2["FortifyFPR"] = "FortifyFPR";
1860
+ return ConvertToSarifInputFileFormat2;
1861
+ })(ConvertToSarifInputFileFormat || {});
1633
1862
 
1634
- // src/constants.ts
1635
- var debug = Debug("mobbdev:constants");
1636
- var __dirname = path.dirname(fileURLToPath(import.meta.url));
1637
- dotenv.config({ path: path.join(__dirname, "../.env") });
1638
- var scmFriendlyText = {
1639
- ["Ado" /* Ado */]: "Azure DevOps",
1640
- ["Bitbucket" /* Bitbucket */]: "Bitbucket",
1641
- ["GitHub" /* GitHub */]: "GitGub",
1642
- ["GitLab" /* GitLab */]: "GitLab"
1643
- };
1644
- var SCANNERS = {
1645
- Checkmarx: "checkmarx",
1646
- Codeql: "codeql",
1647
- Fortify: "fortify",
1648
- Snyk: "snyk",
1649
- Sonarqube: "sonarqube",
1650
- Semgrep: "semgrep",
1651
- Datadog: "datadog"
1652
- };
1653
- var scannerToVulnerability_Report_Vendor_Enum = {
1654
- [SCANNERS.Checkmarx]: "checkmarx" /* Checkmarx */,
1655
- [SCANNERS.Snyk]: "snyk" /* Snyk */,
1656
- [SCANNERS.Sonarqube]: "sonarqube" /* Sonarqube */,
1657
- [SCANNERS.Codeql]: "codeql" /* Codeql */,
1658
- [SCANNERS.Fortify]: "fortify" /* Fortify */,
1659
- [SCANNERS.Semgrep]: "semgrep" /* Semgrep */,
1660
- [SCANNERS.Datadog]: "datadog" /* Datadog */
1661
- };
1662
- var SupportedScannersZ = z8.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
1663
- var envVariablesSchema = z8.object({
1664
- WEB_APP_URL: z8.string(),
1665
- API_URL: z8.string(),
1666
- HASURA_ACCESS_KEY: z8.string(),
1667
- LOCAL_GRAPHQL_ENDPOINT: z8.string(),
1668
- HTTP_PROXY: z8.string().optional().default(""),
1669
- HTTPS_PROXY: z8.string().optional().default("")
1670
- }).required();
1671
- var envVariables = envVariablesSchema.parse(process.env);
1672
- debug("config %o", envVariables);
1673
- var mobbAscii = `
1674
- ..
1675
- ..........
1676
- .................
1677
- ...........................
1678
- ..............................
1679
- ................................
1680
- ..................................
1681
- ....................................
1682
- .....................................
1683
- .............................................
1684
- .................................................
1685
- ............................... .................
1686
- .................................. ............
1687
- .................. ............. ..........
1688
- ......... ........ ......... ......
1689
- ............... ....
1690
- .... ..
1691
-
1692
- . ...
1693
- ..............
1694
- ......................
1695
- ...........................
1696
- ................................
1697
- ......................................
1698
- ...............................
1699
- .................
1700
- `;
1701
- var PROJECT_DEFAULT_NAME = "My first project";
1702
- var WEB_APP_URL = envVariables.WEB_APP_URL;
1703
- var API_URL = envVariables.API_URL;
1704
- var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
1705
- var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
1706
- var HTTPS_PROXY = envVariables.HTTPS_PROXY;
1707
- var HTTP_PROXY = envVariables.HTTP_PROXY;
1708
- var errorMessages = {
1709
- missingCxProjectName: `project name ${chalk.bold(
1710
- "(--cx-project-name)"
1711
- )} is needed if you're using checkmarx`,
1712
- missingUrl: `url ${chalk.bold(
1713
- "(--url)"
1714
- )} is needed if you're adding an SCM token`,
1715
- invalidScmType: `SCM type ${chalk.bold(
1716
- "(--scm-type)"
1717
- )} is invalid, please use one of: ${Object.values(ScmType).join(", ")}`,
1718
- missingToken: `SCM token ${chalk.bold(
1719
- "(--token)"
1720
- )} is needed if you're adding an SCM token`
1721
- };
1722
- var progressMassages = {
1723
- processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
1724
- processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
1725
- processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
1726
- };
1727
- var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
1863
+ // src/features/analysis/scm/ado/constants.ts
1864
+ var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
1728
1865
 
1729
- // src/features/analysis/index.ts
1730
- import fs3 from "node:fs";
1731
- import fsPromises from "node:fs/promises";
1732
- import path6 from "node:path";
1733
- import { env as env2 } from "node:process";
1734
- import { pipeline } from "node:stream/promises";
1866
+ // src/features/analysis/scm/ado/utils.ts
1867
+ import querystring from "node:querystring";
1868
+ import * as api from "azure-devops-node-api";
1869
+ import Debug from "debug";
1870
+ import { z as z17 } from "zod";
1735
1871
 
1736
- // src/utils/index.ts
1737
- var utils_exports = {};
1738
- __export(utils_exports, {
1739
- CliError: () => CliError,
1740
- Spinner: () => Spinner,
1741
- getDirName: () => getDirName,
1742
- getTopLevelDirName: () => getTopLevelDirName,
1743
- keypress: () => keypress,
1744
- packageJson: () => packageJson,
1745
- sleep: () => sleep
1872
+ // src/features/analysis/scm/env.ts
1873
+ import { z as z8 } from "zod";
1874
+ var EnvVariablesZod = z8.object({
1875
+ GITLAB_API_TOKEN: z8.string().optional(),
1876
+ GITHUB_API_TOKEN: z8.string().optional(),
1877
+ GIT_PROXY_HOST: z8.string().optional().default("http://tinyproxy:8888")
1746
1878
  });
1879
+ var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
1747
1880
 
1748
- // src/utils/dirname.ts
1749
- import path2 from "node:path";
1750
- import { fileURLToPath as fileURLToPath2 } from "node:url";
1751
- function getDirName() {
1752
- return path2.dirname(fileURLToPath2(import.meta.url));
1753
- }
1754
- function getTopLevelDirName(fullPath) {
1755
- return path2.parse(fullPath).name;
1756
- }
1757
-
1758
- // src/utils/keypress.ts
1759
- import readline from "node:readline";
1760
- async function keypress() {
1761
- const rl = readline.createInterface({
1762
- input: process.stdin,
1763
- output: process.stdout
1764
- });
1765
- return new Promise((resolve) => {
1766
- rl.question("", (answer) => {
1767
- rl.close();
1768
- process.stderr.moveCursor(0, -1);
1769
- process.stderr.clearLine(1);
1770
- resolve(answer);
1771
- });
1772
- });
1773
- }
1881
+ // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
1882
+ import { z as z9 } from "zod";
1774
1883
 
1775
- // src/utils/spinner.ts
1776
- import {
1777
- createSpinner as _createSpinner
1778
- } from "nanospinner";
1779
- function printToStdError(opts) {
1780
- if (opts?.text) console.error(opts.text);
1781
- }
1782
- var mockSpinner = {
1783
- success: (opts) => {
1784
- printToStdError(opts);
1785
- return mockSpinner;
1884
+ // src/features/analysis/scm/shared/src/fixDetailsData.ts
1885
+ var fixDetailsData = {
1886
+ ["PT" /* Pt */]: {
1887
+ issueDescription: "Path Traversal AKA Directory Traversal occurs when a path coming from user input is not properly sanitized, allowing an attacker to navigate through directories beyond the intended scope. Attackers can exploit this to access sensitive files or execute arbitrary code.",
1888
+ fixInstructions: "Sanitize user-supplied paths, ensuring that they are restricted to a predefined directory structure."
1786
1889
  },
1787
- error: (opts) => {
1788
- printToStdError(opts);
1789
- return mockSpinner;
1890
+ ["ZIP_SLIP" /* ZipSlip */]: {
1891
+ issueDescription: "Zip Slip is a form of directory traversal that can be exploited by extracting files from an archive. Attackers can manipulate archive files to overwrite sensitive files or execute arbitrary code.",
1892
+ fixInstructions: "Ensure that extracted files are relative and within the intended directory structure."
1790
1893
  },
1791
- warn: (opts) => {
1792
- printToStdError(opts);
1793
- return mockSpinner;
1894
+ ["XSS" /* Xss */]: {
1895
+ issueDescription: "Cross-Site Scripting (XSS) allows attackers to inject malicious scripts into web pages viewed by other users. This can lead to theft of session cookies, redirection to malicious websites, or defacement of the webpage.",
1896
+ fixInstructions: "Implement input validation and output encoding. This includes sanitizing user input and escaping special characters to prevent execution of injected scripts."
1794
1897
  },
1795
- stop: (opts) => {
1796
- printToStdError(opts);
1797
- return mockSpinner;
1798
- },
1799
- start: (opts) => {
1800
- printToStdError(opts);
1801
- return mockSpinner;
1802
- },
1803
- update: (opts) => {
1804
- printToStdError(opts);
1805
- return mockSpinner;
1806
- },
1807
- reset: () => mockSpinner,
1808
- clear: () => mockSpinner,
1809
- spin: () => mockSpinner
1810
- };
1811
- function Spinner({ ci = false } = {}) {
1812
- return {
1813
- createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
1814
- };
1815
- }
1816
-
1817
- // src/utils/check_node_version.ts
1818
- import fs from "node:fs";
1819
- import path3 from "node:path";
1820
- import semver from "semver";
1821
- var packageJson = JSON.parse(
1822
- fs.readFileSync(path3.join(getDirName(), "../package.json"), "utf8")
1823
- );
1824
- if (!semver.satisfies(process.version, packageJson.engines.node)) {
1825
- console.error(
1826
- `
1827
- \u26A0\uFE0F ${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
1828
- );
1829
- process.exit(1);
1830
- }
1831
-
1832
- // src/utils/index.ts
1833
- var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
1834
- var CliError = class extends Error {
1835
- };
1836
-
1837
- // src/features/analysis/index.ts
1838
- import chalk4 from "chalk";
1839
- import Configstore from "configstore";
1840
- import Debug18 from "debug";
1841
- import extract from "extract-zip";
1842
- import { createSpinner as createSpinner4 } from "nanospinner";
1843
- import fetch4 from "node-fetch";
1844
- import open2 from "open";
1845
- import tmp from "tmp";
1846
- import { z as z29 } from "zod";
1847
-
1848
- // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
1849
- import Debug8 from "debug";
1850
-
1851
- // src/features/analysis/scm/errors.ts
1852
- var InvalidRepoUrlError = class extends Error {
1853
- constructor(m) {
1854
- super(m);
1855
- }
1856
- };
1857
- var InvalidAccessTokenError = class extends Error {
1858
- constructor(m) {
1859
- super(m);
1860
- }
1861
- };
1862
- var InvalidUrlPatternError = class extends Error {
1863
- constructor(m) {
1864
- super(m);
1865
- }
1866
- };
1867
- var RefNotFoundError = class extends Error {
1868
- constructor(m) {
1869
- super(m);
1870
- }
1871
- };
1872
- var RepoNoTokenAccessError = class extends Error {
1873
- constructor(m, scmType) {
1874
- super(m);
1875
- this.scmType = scmType;
1876
- }
1877
- };
1878
-
1879
- // src/features/analysis/scm/ado/constants.ts
1880
- var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
1881
-
1882
- // src/features/analysis/scm/ado/utils.ts
1883
- import querystring from "node:querystring";
1884
- import * as api from "azure-devops-node-api";
1885
- import Debug2 from "debug";
1886
- import { z as z18 } from "zod";
1887
-
1888
- // src/features/analysis/scm/env.ts
1889
- import { z as z9 } from "zod";
1890
- var EnvVariablesZod = z9.object({
1891
- GITLAB_API_TOKEN: z9.string().optional(),
1892
- GITHUB_API_TOKEN: z9.string().optional(),
1893
- GIT_PROXY_HOST: z9.string()
1894
- });
1895
- var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
1896
-
1897
- // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
1898
- import { z as z10 } from "zod";
1899
-
1900
- // src/features/analysis/scm/shared/src/fixDetailsData.ts
1901
- var fixDetailsData = {
1902
- ["PT" /* Pt */]: {
1903
- issueDescription: "Path Traversal AKA Directory Traversal occurs when a path coming from user input is not properly sanitized, allowing an attacker to navigate through directories beyond the intended scope. Attackers can exploit this to access sensitive files or execute arbitrary code.",
1904
- fixInstructions: "Sanitize user-supplied paths, ensuring that they are restricted to a predefined directory structure."
1905
- },
1906
- ["ZIP_SLIP" /* ZipSlip */]: {
1907
- issueDescription: "Zip Slip is a form of directory traversal that can be exploited by extracting files from an archive. Attackers can manipulate archive files to overwrite sensitive files or execute arbitrary code.",
1908
- fixInstructions: "Ensure that extracted files are relative and within the intended directory structure."
1909
- },
1910
- ["XSS" /* Xss */]: {
1911
- issueDescription: "Cross-Site Scripting (XSS) allows attackers to inject malicious scripts into web pages viewed by other users. This can lead to theft of session cookies, redirection to malicious websites, or defacement of the webpage.",
1912
- fixInstructions: "Implement input validation and output encoding. This includes sanitizing user input and escaping special characters to prevent execution of injected scripts."
1913
- },
1914
- ["XXE" /* Xxe */]: {
1915
- issueDescription: "XML External Entity (XXE) allows attackers to exploit vulnerable XML processors by including external entities, leading to disclosure of confidential data, denial of service, or server-side request forgery.",
1916
- fixInstructions: "Disable external entity processing in XML parsers or update to versions that mitigate XXE vulnerabilities. Input validation should be implemented to ensure that XML input does not contain external entity references."
1898
+ ["XXE" /* Xxe */]: {
1899
+ issueDescription: "XML External Entity (XXE) allows attackers to exploit vulnerable XML processors by including external entities, leading to disclosure of confidential data, denial of service, or server-side request forgery.",
1900
+ fixInstructions: "Disable external entity processing in XML parsers or update to versions that mitigate XXE vulnerabilities. Input validation should be implemented to ensure that XML input does not contain external entity references."
1917
1901
  },
1918
1902
  ["CMDi" /* CmDi */]: {
1919
1903
  issueDescription: "Command Injection (CMDI) allows attackers inject malicious commands into vulnerable applications, that can result in execution of arbitrary commands on the underlying operating system.",
@@ -2147,7 +2131,10 @@ var fixDetailsData = {
2147
2131
  ["RETURN_SHOULD_NOT_BE_INVARIANT" /* ReturnShouldNotBeInvariant */]: void 0,
2148
2132
  ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: void 0,
2149
2133
  ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: void 0,
2150
- ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0
2134
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0,
2135
+ ["AVOID_BUILTIN_SHADOWING" /* AvoidBuiltinShadowing */]: void 0,
2136
+ ["IMPROPER_STRING_FORMATTING" /* ImproperStringFormatting */]: void 0,
2137
+ ["WILDCARD_IMPORTS" /* WildcardImports */]: void 0
2151
2138
  };
2152
2139
 
2153
2140
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
@@ -2178,7 +2165,7 @@ var getCommitDescription = ({
2178
2165
  )}**.
2179
2166
 
2180
2167
  `;
2181
- const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2168
+ const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2182
2169
  if (issueType && parseIssueTypeRes.success) {
2183
2170
  if (irrelevantIssueWithTags?.[0]?.tag) {
2184
2171
  description += `
@@ -2221,7 +2208,7 @@ var getCommitIssueDescription = ({
2221
2208
  const issueTypeString = getIssueTypeFriendlyString(issueType);
2222
2209
  let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
2223
2210
  `;
2224
- const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2211
+ const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2225
2212
  if (issueType && parseIssueTypeRes.success) {
2226
2213
  if (irrelevantIssueWithTags?.[0]?.tag) {
2227
2214
  description = `
@@ -2246,10 +2233,10 @@ ${staticData.issueDescription}
2246
2233
  };
2247
2234
 
2248
2235
  // src/features/analysis/scm/shared/src/guidances.ts
2249
- import { z as z13 } from "zod";
2236
+ import { z as z12 } from "zod";
2250
2237
 
2251
2238
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2252
- import { z as z11 } from "zod";
2239
+ import { z as z10 } from "zod";
2253
2240
 
2254
2241
  // src/features/analysis/scm/shared/src/storedFixData/passwordInComment.ts
2255
2242
  var passwordInComment = {
@@ -2425,8 +2412,8 @@ var vulnerabilities8 = {
2425
2412
  var xml_default = vulnerabilities8;
2426
2413
 
2427
2414
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2428
- var StoredFixDataItemZ = z11.object({
2429
- guidance: z11.function().returns(z11.string())
2415
+ var StoredFixDataItemZ = z10.object({
2416
+ guidance: z10.function().returns(z10.string())
2430
2417
  });
2431
2418
  var languages = {
2432
2419
  ["Java" /* Java */]: java_default,
@@ -2440,7 +2427,7 @@ var languages = {
2440
2427
  };
2441
2428
 
2442
2429
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
2443
- import { z as z12 } from "zod";
2430
+ import { z as z11 } from "zod";
2444
2431
 
2445
2432
  // src/features/analysis/scm/shared/src/storedQuestionData/csharp/httpOnlyCookie.ts
2446
2433
  var httpOnlyCookie = {
@@ -3639,10 +3626,10 @@ var vulnerabilities14 = {
3639
3626
  var xml_default2 = vulnerabilities14;
3640
3627
 
3641
3628
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
3642
- var StoredQuestionDataItemZ = z12.object({
3643
- content: z12.function().args(z12.any()).returns(z12.string()),
3644
- description: z12.function().args(z12.any()).returns(z12.string()),
3645
- guidance: z12.function().args(z12.any()).returns(z12.string())
3629
+ var StoredQuestionDataItemZ = z11.object({
3630
+ content: z11.function().args(z11.any()).returns(z11.string()),
3631
+ description: z11.function().args(z11.any()).returns(z11.string()),
3632
+ guidance: z11.function().args(z11.any()).returns(z11.string())
3646
3633
  });
3647
3634
  var languages2 = {
3648
3635
  ["Java" /* Java */]: java_default2,
@@ -3737,9 +3724,9 @@ function getFixGuidances({
3737
3724
  const fixGuidance = storeFixResult.success ? [storeFixResult.data.guidance({ questions, ...extraContext })] : [];
3738
3725
  return libGuidances.concat(fixGuidance).filter((guidance) => !!guidance);
3739
3726
  }
3740
- var IssueTypeAndLanguageZ = z13.object({
3741
- issueType: z13.nativeEnum(IssueType_Enum),
3742
- issueLanguage: z13.nativeEnum(IssueLanguage_Enum)
3727
+ var IssueTypeAndLanguageZ = z12.object({
3728
+ issueType: z12.nativeEnum(IssueType_Enum),
3729
+ issueLanguage: z12.nativeEnum(IssueLanguage_Enum)
3743
3730
  });
3744
3731
  function getGuidances(args) {
3745
3732
  const safeIssueTypeAndLanguage = IssueTypeAndLanguageZ.safeParse({
@@ -3777,7 +3764,7 @@ function getGuidances(args) {
3777
3764
  }
3778
3765
 
3779
3766
  // src/features/analysis/scm/shared/src/urlParser/urlParser.ts
3780
- import { z as z14 } from "zod";
3767
+ import { z as z13 } from "zod";
3781
3768
  var ADO_PREFIX_PATH = "tfs";
3782
3769
  var NAME_REGEX = /[a-z0-9\-_.+]+/i;
3783
3770
  function detectAdoUrl(args) {
@@ -3794,7 +3781,7 @@ function detectAdoUrl(args) {
3794
3781
  scmType: "Ado" /* Ado */,
3795
3782
  organization,
3796
3783
  // project has single repo - repoName === projectName
3797
- projectName: z14.string().parse(projectName),
3784
+ projectName: z13.string().parse(projectName),
3798
3785
  repoName: projectName,
3799
3786
  prefixPath
3800
3787
  };
@@ -3805,7 +3792,7 @@ function detectAdoUrl(args) {
3805
3792
  return {
3806
3793
  scmType: "Ado" /* Ado */,
3807
3794
  organization,
3808
- projectName: z14.string().parse(projectName),
3795
+ projectName: z13.string().parse(projectName),
3809
3796
  repoName,
3810
3797
  prefixPath
3811
3798
  };
@@ -3819,7 +3806,7 @@ function detectAdoUrl(args) {
3819
3806
  scmType: "Ado" /* Ado */,
3820
3807
  organization,
3821
3808
  // project has only one repo - repoName === projectName
3822
- projectName: z14.string().parse(repoName),
3809
+ projectName: z13.string().parse(repoName),
3823
3810
  repoName,
3824
3811
  prefixPath
3825
3812
  };
@@ -3829,7 +3816,7 @@ function detectAdoUrl(args) {
3829
3816
  return {
3830
3817
  scmType: "Ado" /* Ado */,
3831
3818
  organization,
3832
- projectName: z14.string().parse(projectName),
3819
+ projectName: z13.string().parse(projectName),
3833
3820
  repoName,
3834
3821
  prefixPath
3835
3822
  };
@@ -3956,10 +3943,10 @@ function getIssueUrl({
3956
3943
  }
3957
3944
 
3958
3945
  // src/features/analysis/scm/utils/index.ts
3959
- import { z as z16 } from "zod";
3946
+ import { z as z15 } from "zod";
3960
3947
 
3961
3948
  // src/features/analysis/scm/types.ts
3962
- import { z as z15 } from "zod";
3949
+ import { z as z14 } from "zod";
3963
3950
  var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
3964
3951
  ReferenceType2["BRANCH"] = "BRANCH";
3965
3952
  ReferenceType2["COMMIT"] = "COMMIT";
@@ -3991,10 +3978,10 @@ var scmTypeToScmLibScmType = {
3991
3978
  ["Ado" /* Ado */]: "ADO" /* ADO */,
3992
3979
  ["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
3993
3980
  };
3994
- var GetRefererenceResultZ = z15.object({
3995
- date: z15.date().optional(),
3996
- sha: z15.string(),
3997
- type: z15.nativeEnum(ReferenceType)
3981
+ var GetRefererenceResultZ = z14.object({
3982
+ date: z14.date().optional(),
3983
+ sha: z14.string(),
3984
+ type: z14.nativeEnum(ReferenceType)
3998
3985
  });
3999
3986
 
4000
3987
  // src/features/analysis/scm/utils/index.ts
@@ -4108,7 +4095,7 @@ function shouldValidateUrl(repoUrl) {
4108
4095
  return repoUrl && isUrlHasPath(repoUrl);
4109
4096
  }
4110
4097
  function isBrokerUrl(url) {
4111
- return z16.string().uuid().safeParse(new URL(url).host).success;
4098
+ return z15.string().uuid().safeParse(new URL(url).host).success;
4112
4099
  }
4113
4100
  function buildAuthorizedRepoUrl(args) {
4114
4101
  const { url, username, password } = args;
@@ -4144,7 +4131,7 @@ function getCloudScmLibTypeFromUrl(url) {
4144
4131
  return void 0;
4145
4132
  }
4146
4133
  function getScmLibTypeFromScmType(scmType) {
4147
- const parsedScmType = z16.nativeEnum(ScmType).parse(scmType);
4134
+ const parsedScmType = z15.nativeEnum(ScmType).parse(scmType);
4148
4135
  return scmTypeToScmLibScmType[parsedScmType];
4149
4136
  }
4150
4137
  function getScmConfig({
@@ -4211,42 +4198,42 @@ function getScmConfig({
4211
4198
  }
4212
4199
 
4213
4200
  // src/features/analysis/scm/ado/validation.ts
4214
- import { z as z17 } from "zod";
4215
- var ValidPullRequestStatusZ = z17.union([
4216
- z17.literal(1 /* Active */),
4217
- z17.literal(2 /* Abandoned */),
4218
- z17.literal(3 /* Completed */)
4201
+ import { z as z16 } from "zod";
4202
+ var ValidPullRequestStatusZ = z16.union([
4203
+ z16.literal(1 /* Active */),
4204
+ z16.literal(2 /* Abandoned */),
4205
+ z16.literal(3 /* Completed */)
4219
4206
  ]);
4220
- var AdoAuthResultZ = z17.object({
4221
- access_token: z17.string().min(1),
4222
- token_type: z17.string().min(1),
4223
- refresh_token: z17.string().min(1)
4207
+ var AdoAuthResultZ = z16.object({
4208
+ access_token: z16.string().min(1),
4209
+ token_type: z16.string().min(1),
4210
+ refresh_token: z16.string().min(1)
4224
4211
  });
4225
4212
  var AdoAuthResultWithOrgsZ = AdoAuthResultZ.extend({
4226
- scmOrgs: z17.array(z17.string())
4213
+ scmOrgs: z16.array(z16.string())
4227
4214
  });
4228
- var profileZ = z17.object({
4229
- displayName: z17.string(),
4230
- publicAlias: z17.string().min(1),
4231
- emailAddress: z17.string(),
4232
- coreRevision: z17.number(),
4233
- timeStamp: z17.string(),
4234
- id: z17.string(),
4235
- revision: z17.number()
4215
+ var profileZ = z16.object({
4216
+ displayName: z16.string(),
4217
+ publicAlias: z16.string().min(1),
4218
+ emailAddress: z16.string(),
4219
+ coreRevision: z16.number(),
4220
+ timeStamp: z16.string(),
4221
+ id: z16.string(),
4222
+ revision: z16.number()
4236
4223
  });
4237
- var accountsZ = z17.object({
4238
- count: z17.number(),
4239
- value: z17.array(
4240
- z17.object({
4241
- accountId: z17.string(),
4242
- accountUri: z17.string(),
4243
- accountName: z17.string()
4224
+ var accountsZ = z16.object({
4225
+ count: z16.number(),
4226
+ value: z16.array(
4227
+ z16.object({
4228
+ accountId: z16.string(),
4229
+ accountUri: z16.string(),
4230
+ accountName: z16.string()
4244
4231
  })
4245
4232
  )
4246
4233
  });
4247
4234
 
4248
4235
  // src/features/analysis/scm/ado/utils.ts
4249
- var debug2 = Debug2("mobbdev:scm:ado");
4236
+ var debug = Debug("mobbdev:scm:ado");
4250
4237
  function _getPublicAdoClient({
4251
4238
  orgName,
4252
4239
  origin: origin2
@@ -4325,7 +4312,7 @@ async function getAdoConnectData({
4325
4312
  oauthToken: adoTokenInfo.accessToken
4326
4313
  });
4327
4314
  return {
4328
- org: z18.string().parse(org),
4315
+ org: z17.string().parse(org),
4329
4316
  origin: DEFUALT_ADO_ORIGIN
4330
4317
  };
4331
4318
  }
@@ -4411,7 +4398,7 @@ async function getAdoClientParams(params) {
4411
4398
  return {
4412
4399
  tokenType: "PAT" /* PAT */,
4413
4400
  accessToken: adoTokenInfo.accessToken,
4414
- patTokenOrg: z18.string().parse(tokenOrg).toLowerCase(),
4401
+ patTokenOrg: z17.string().parse(tokenOrg).toLowerCase(),
4415
4402
  origin: origin2,
4416
4403
  orgName: org.toLowerCase()
4417
4404
  };
@@ -4579,6 +4566,18 @@ async function getAdoSdk(params) {
4579
4566
  );
4580
4567
  return `${getRepositoryRes.webUrl}/commit/${commitId}`;
4581
4568
  },
4569
+ async getAdoBranchCommitsUrl({
4570
+ repoUrl,
4571
+ branch
4572
+ }) {
4573
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
4574
+ const git = await api2.getGitApi();
4575
+ const getRepositoryRes = await git.getRepository(
4576
+ decodeURI(repo),
4577
+ projectName ? decodeURI(projectName) : void 0
4578
+ );
4579
+ return `${getRepositoryRes.webUrl}/commits?itemVersion=${branch}`;
4580
+ },
4582
4581
  getAdoDownloadUrl({
4583
4582
  repoUrl,
4584
4583
  branch
@@ -4587,7 +4586,7 @@ async function getAdoSdk(params) {
4587
4586
  const url = new URL(repoUrl);
4588
4587
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
4589
4588
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
4590
- const path8 = [
4589
+ const path9 = [
4591
4590
  prefixPath,
4592
4591
  owner,
4593
4592
  projectName,
@@ -4598,7 +4597,7 @@ async function getAdoSdk(params) {
4598
4597
  "items",
4599
4598
  "items"
4600
4599
  ].filter(Boolean).join("/");
4601
- return new URL(`${path8}?${params2}`, origin2).toString();
4600
+ return new URL(`${path9}?${params2}`, origin2).toString();
4602
4601
  },
4603
4602
  async getAdoBranchList({ repoUrl }) {
4604
4603
  try {
@@ -5080,6 +5079,14 @@ var AdoSCMLib = class extends SCMLib {
5080
5079
  commitId
5081
5080
  });
5082
5081
  }
5082
+ async getBranchCommitsUrl(branchName) {
5083
+ this._validateUrl();
5084
+ const adoSdk = await this.getAdoSdk();
5085
+ return adoSdk.getAdoBranchCommitsUrl({
5086
+ repoUrl: this.url,
5087
+ branch: branchName
5088
+ });
5089
+ }
5083
5090
  async addCommentToSubmitRequest(scmSubmitRequestId, comment) {
5084
5091
  this._validateAccessTokenAndUrl();
5085
5092
  const adoSdk = await this.getAdoSdk();
@@ -5095,34 +5102,34 @@ var AdoSCMLib = class extends SCMLib {
5095
5102
  import querystring2 from "node:querystring";
5096
5103
  import * as bitbucketPkgNode from "bitbucket";
5097
5104
  import bitbucketPkg from "bitbucket";
5098
- import Debug3 from "debug";
5099
- import { z as z20 } from "zod";
5105
+ import Debug2 from "debug";
5106
+ import { z as z19 } from "zod";
5100
5107
 
5101
5108
  // src/features/analysis/scm/bitbucket/validation.ts
5102
- import { z as z19 } from "zod";
5103
- var BitbucketAuthResultZ = z19.object({
5104
- access_token: z19.string(),
5105
- token_type: z19.string(),
5106
- refresh_token: z19.string()
5109
+ import { z as z18 } from "zod";
5110
+ var BitbucketAuthResultZ = z18.object({
5111
+ access_token: z18.string(),
5112
+ token_type: z18.string(),
5113
+ refresh_token: z18.string()
5107
5114
  });
5108
5115
 
5109
5116
  // src/features/analysis/scm/bitbucket/bitbucket.ts
5110
- var debug3 = Debug3("scm:bitbucket");
5117
+ var debug2 = Debug2("scm:bitbucket");
5111
5118
  var BITBUCKET_HOSTNAME = "bitbucket.org";
5112
- var TokenExpiredErrorZ = z20.object({
5113
- status: z20.number(),
5114
- error: z20.object({
5115
- type: z20.string(),
5116
- error: z20.object({
5117
- message: z20.string()
5119
+ var TokenExpiredErrorZ = z19.object({
5120
+ status: z19.number(),
5121
+ error: z19.object({
5122
+ type: z19.string(),
5123
+ error: z19.object({
5124
+ message: z19.string()
5118
5125
  })
5119
5126
  })
5120
5127
  });
5121
5128
  var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
5122
- var BitbucketParseResultZ = z20.object({
5123
- organization: z20.string(),
5124
- repoName: z20.string(),
5125
- hostname: z20.literal(BITBUCKET_HOSTNAME)
5129
+ var BitbucketParseResultZ = z19.object({
5130
+ organization: z19.string(),
5131
+ repoName: z19.string(),
5132
+ hostname: z19.literal(BITBUCKET_HOSTNAME)
5126
5133
  });
5127
5134
  function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
5128
5135
  const parsedGitHubUrl = normalizeUrl(bitbucketUrl);
@@ -5183,7 +5190,7 @@ function getBitbucketSdk(params) {
5183
5190
  if (!res.data.values) {
5184
5191
  return [];
5185
5192
  }
5186
- return res.data.values.filter((branch) => !!branch.name).map((branch) => z20.string().parse(branch.name));
5193
+ return res.data.values.filter((branch) => !!branch.name).map((branch) => z19.string().parse(branch.name));
5187
5194
  },
5188
5195
  async getIsUserCollaborator(params2) {
5189
5196
  const { repoUrl } = params2;
@@ -5298,7 +5305,7 @@ function getBitbucketSdk(params) {
5298
5305
  return GetRefererenceResultZ.parse({
5299
5306
  sha: tagRes.data.target?.hash,
5300
5307
  type: "TAG" /* TAG */,
5301
- date: new Date(z20.string().parse(tagRes.data.target?.date))
5308
+ date: new Date(z19.string().parse(tagRes.data.target?.date))
5302
5309
  });
5303
5310
  },
5304
5311
  async getBranchRef(params2) {
@@ -5306,7 +5313,7 @@ function getBitbucketSdk(params) {
5306
5313
  return GetRefererenceResultZ.parse({
5307
5314
  sha: getBranchRes.target?.hash,
5308
5315
  type: "BRANCH" /* BRANCH */,
5309
- date: new Date(z20.string().parse(getBranchRes.target?.date))
5316
+ date: new Date(z19.string().parse(getBranchRes.target?.date))
5310
5317
  });
5311
5318
  },
5312
5319
  async getCommitRef(params2) {
@@ -5314,13 +5321,13 @@ function getBitbucketSdk(params) {
5314
5321
  return GetRefererenceResultZ.parse({
5315
5322
  sha: getCommitRes.hash,
5316
5323
  type: "COMMIT" /* COMMIT */,
5317
- date: new Date(z20.string().parse(getCommitRes.date))
5324
+ date: new Date(z19.string().parse(getCommitRes.date))
5318
5325
  });
5319
5326
  },
5320
5327
  async getDownloadUrl({ url, sha }) {
5321
5328
  this.getReferenceData({ ref: sha, url });
5322
5329
  const repoRes = await this.getRepo({ repoUrl: url });
5323
- const parsedRepoUrl = z20.string().url().parse(repoRes.links?.html?.href);
5330
+ const parsedRepoUrl = z19.string().url().parse(repoRes.links?.html?.href);
5324
5331
  return `${parsedRepoUrl}/get/${sha}.zip`;
5325
5332
  },
5326
5333
  async getPullRequest(params2) {
@@ -5385,7 +5392,7 @@ async function validateBitbucketParams(params) {
5385
5392
  }
5386
5393
  async function getUsersworkspacesSlugs(bitbucketClient) {
5387
5394
  const res = await bitbucketClient.workspaces.getWorkspaces({});
5388
- return res.data.values?.map((v) => z20.string().parse(v.slug));
5395
+ return res.data.values?.map((v) => z19.string().parse(v.slug));
5389
5396
  }
5390
5397
  async function getllUsersrepositories(bitbucketClient) {
5391
5398
  const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
@@ -5413,10 +5420,10 @@ async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
5413
5420
 
5414
5421
  // src/features/analysis/scm/bitbucket/BitbucketSCMLib.ts
5415
5422
  import { setTimeout as setTimeout3 } from "node:timers/promises";
5416
- import { z as z21 } from "zod";
5423
+ import { z as z20 } from "zod";
5417
5424
  function getUserAndPassword(token) {
5418
5425
  const [username, password] = token.split(":");
5419
- const safePasswordAndUsername = z21.object({ username: z21.string(), password: z21.string() }).parse({ username, password });
5426
+ const safePasswordAndUsername = z20.object({ username: z20.string(), password: z20.string() }).parse({ username, password });
5420
5427
  return {
5421
5428
  username: safePasswordAndUsername.username,
5422
5429
  password: safePasswordAndUsername.password
@@ -5488,7 +5495,7 @@ var BitbucketSCMLib = class extends SCMLib {
5488
5495
  return { username, password, authType };
5489
5496
  }
5490
5497
  case "token": {
5491
- return { authType, token: z21.string().parse(this.accessToken) };
5498
+ return { authType, token: z20.string().parse(this.accessToken) };
5492
5499
  }
5493
5500
  case "public":
5494
5501
  return { authType };
@@ -5502,7 +5509,7 @@ var BitbucketSCMLib = class extends SCMLib {
5502
5509
  ...params,
5503
5510
  repoUrl: this.url
5504
5511
  });
5505
- return String(z21.number().parse(pullRequestRes.id));
5512
+ return String(z20.number().parse(pullRequestRes.id));
5506
5513
  } catch (e) {
5507
5514
  console.warn(
5508
5515
  `error creating pull request for BB. Try number ${i + 1}`,
@@ -5587,7 +5594,7 @@ var BitbucketSCMLib = class extends SCMLib {
5587
5594
  async getUsername() {
5588
5595
  this._validateAccessToken();
5589
5596
  const res = await this.bitbucketSdk.getUser();
5590
- return z21.string().parse(res.username);
5597
+ return z20.string().parse(res.username);
5591
5598
  }
5592
5599
  async getSubmitRequestStatus(_scmSubmitRequestId) {
5593
5600
  this._validateAccessTokenAndUrl();
@@ -5616,7 +5623,7 @@ var BitbucketSCMLib = class extends SCMLib {
5616
5623
  async getRepoDefaultBranch() {
5617
5624
  this._validateUrl();
5618
5625
  const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
5619
- return z21.string().parse(repoRes.mainbranch?.name);
5626
+ return z20.string().parse(repoRes.mainbranch?.name);
5620
5627
  }
5621
5628
  getSubmitRequestUrl(submitRequestId) {
5622
5629
  this._validateUrl();
@@ -5636,6 +5643,13 @@ var BitbucketSCMLib = class extends SCMLib {
5636
5643
  `https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
5637
5644
  );
5638
5645
  }
5646
+ getBranchCommitsUrl(branchName) {
5647
+ this._validateUrl();
5648
+ const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
5649
+ return Promise.resolve(
5650
+ `https://bitbucket.org/${workspace}/${repo_slug}/branch/${branchName}`
5651
+ );
5652
+ }
5639
5653
  async addCommentToSubmitRequest(submitRequestId, comment) {
5640
5654
  this._validateUrl();
5641
5655
  await this.bitbucketSdk.addCommentToPullRequest({
@@ -5651,7 +5665,7 @@ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
5651
5665
  var MAX_BRANCHES_FETCH = 1e3;
5652
5666
 
5653
5667
  // src/features/analysis/scm/github/GithubSCMLib.ts
5654
- import { z as z22 } from "zod";
5668
+ import { z as z21 } from "zod";
5655
5669
 
5656
5670
  // src/features/analysis/scm/github/github.ts
5657
5671
  import { RequestError } from "@octokit/request-error";
@@ -6040,14 +6054,14 @@ function getGithubSdk(params = {}) {
6040
6054
  };
6041
6055
  },
6042
6056
  async getGithubBlameRanges(params2) {
6043
- const { ref, gitHubUrl, path: path8 } = params2;
6057
+ const { ref, gitHubUrl, path: path9 } = params2;
6044
6058
  const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
6045
6059
  const res = await octokit.graphql(
6046
6060
  GET_BLAME_DOCUMENT,
6047
6061
  {
6048
6062
  owner,
6049
6063
  repo,
6050
- path: path8,
6064
+ path: path9,
6051
6065
  ref
6052
6066
  }
6053
6067
  );
@@ -6289,7 +6303,7 @@ var GithubSCMLib = class extends SCMLib {
6289
6303
  owner,
6290
6304
  repo
6291
6305
  });
6292
- return z22.string().parse(prRes.data);
6306
+ return z21.string().parse(prRes.data);
6293
6307
  }
6294
6308
  async getRepoList(_scmOrg) {
6295
6309
  this._validateAccessToken();
@@ -6353,11 +6367,11 @@ var GithubSCMLib = class extends SCMLib {
6353
6367
  markdownComment: comment
6354
6368
  });
6355
6369
  }
6356
- async getRepoBlameRanges(ref, path8) {
6370
+ async getRepoBlameRanges(ref, path9) {
6357
6371
  this._validateUrl();
6358
6372
  return await this.githubSdk.getGithubBlameRanges({
6359
6373
  ref,
6360
- path: path8,
6374
+ path: path9,
6361
6375
  gitHubUrl: this.url
6362
6376
  });
6363
6377
  }
@@ -6402,6 +6416,10 @@ var GithubSCMLib = class extends SCMLib {
6402
6416
  });
6403
6417
  return getCommitRes.data.html_url;
6404
6418
  }
6419
+ async getBranchCommitsUrl(branchName) {
6420
+ this._validateAccessTokenAndUrl();
6421
+ return `${this.url}/commits/${branchName}`;
6422
+ }
6405
6423
  async postGeneralPrComment(params) {
6406
6424
  const { prNumber, body } = params;
6407
6425
  this._validateAccessTokenAndUrl();
@@ -6445,22 +6463,22 @@ import {
6445
6463
  AccessLevel,
6446
6464
  Gitlab
6447
6465
  } from "@gitbeaker/rest";
6448
- import Debug4 from "debug";
6466
+ import Debug3 from "debug";
6449
6467
  import {
6450
6468
  fetch as undiciFetch,
6451
6469
  ProxyAgent as ProxyAgent2
6452
6470
  } from "undici";
6453
6471
 
6454
6472
  // src/features/analysis/scm/gitlab/types.ts
6455
- import { z as z23 } from "zod";
6456
- var GitlabAuthResultZ = z23.object({
6457
- access_token: z23.string(),
6458
- token_type: z23.string(),
6459
- refresh_token: z23.string()
6473
+ import { z as z22 } from "zod";
6474
+ var GitlabAuthResultZ = z22.object({
6475
+ access_token: z22.string(),
6476
+ token_type: z22.string(),
6477
+ refresh_token: z22.string()
6460
6478
  });
6461
6479
 
6462
6480
  // src/features/analysis/scm/gitlab/gitlab.ts
6463
- var debug4 = Debug4("scm:gitlab");
6481
+ var debug3 = Debug3("scm:gitlab");
6464
6482
  function removeTrailingSlash2(str) {
6465
6483
  return str.trim().replace(/\/+$/, "");
6466
6484
  }
@@ -6755,13 +6773,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
6755
6773
  const { organization, repoName, projectPath } = parsingResult;
6756
6774
  return { owner: organization, repo: repoName, projectPath };
6757
6775
  }
6758
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
6776
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path9 }, options) {
6759
6777
  const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
6760
6778
  const api2 = getGitBeaker({
6761
6779
  url: gitlabUrl,
6762
6780
  gitlabAuthToken: options?.gitlabAuthToken
6763
6781
  });
6764
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
6782
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path9, ref);
6765
6783
  let lineNumber = 1;
6766
6784
  return resp.filter((range) => range.lines).map((range) => {
6767
6785
  const oldLineNumber = lineNumber;
@@ -6937,10 +6955,10 @@ var GitlabSCMLib = class extends SCMLib {
6937
6955
  markdownComment: comment
6938
6956
  });
6939
6957
  }
6940
- async getRepoBlameRanges(ref, path8) {
6958
+ async getRepoBlameRanges(ref, path9) {
6941
6959
  this._validateUrl();
6942
6960
  return await getGitlabBlameRanges(
6943
- { ref, path: path8, gitlabUrl: this.url },
6961
+ { ref, path: path9, gitlabUrl: this.url },
6944
6962
  {
6945
6963
  url: this.url,
6946
6964
  gitlabAuthToken: this.accessToken
@@ -6986,141 +7004,677 @@ var GitlabSCMLib = class extends SCMLib {
6986
7004
  });
6987
7005
  return res.web_url;
6988
7006
  }
7007
+ async getBranchCommitsUrl(branchName) {
7008
+ this._validateAccessTokenAndUrl();
7009
+ return `${this.url}/-/commits/${branchName}`;
7010
+ }
7011
+ };
7012
+
7013
+ // src/features/analysis/scm/scmFactory.ts
7014
+ import { z as z23 } from "zod";
7015
+
7016
+ // src/features/analysis/scm/StubSCMLib.ts
7017
+ var StubSCMLib = class extends SCMLib {
7018
+ constructor(url, accessToken, scmOrg) {
7019
+ super(url, accessToken, scmOrg);
7020
+ }
7021
+ async getUrlWithCredentials() {
7022
+ console.warn("getUrlWithCredentials() returning empty string");
7023
+ return "";
7024
+ }
7025
+ async createSubmitRequest(_params) {
7026
+ console.warn("createSubmitRequest() returning empty string");
7027
+ return "";
7028
+ }
7029
+ get scmLibType() {
7030
+ console.warn("scmLibType returning GITHUB as default");
7031
+ return "GITHUB" /* GITHUB */;
7032
+ }
7033
+ getAuthHeaders() {
7034
+ console.warn("getAuthHeaders() returning empty object");
7035
+ return {};
7036
+ }
7037
+ async getDownloadUrl(_sha) {
7038
+ console.warn("getDownloadUrl() returning empty string");
7039
+ return "";
7040
+ }
7041
+ async getIsRemoteBranch(_branch) {
7042
+ console.warn("getIsRemoteBranch() returning false");
7043
+ return false;
7044
+ }
7045
+ async validateParams() {
7046
+ console.warn("validateParams() no-op");
7047
+ }
7048
+ async getRepoList(_scmOrg) {
7049
+ console.warn("getRepoList() returning empty array");
7050
+ return [];
7051
+ }
7052
+ async getBranchList() {
7053
+ console.warn("getBranchList() returning empty array");
7054
+ return [];
7055
+ }
7056
+ async getUsername() {
7057
+ console.warn("getUsername() returning empty string");
7058
+ return "";
7059
+ }
7060
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
7061
+ console.warn("getSubmitRequestStatus() returning ERROR");
7062
+ return "error";
7063
+ }
7064
+ async getUserHasAccessToRepo() {
7065
+ console.warn("getUserHasAccessToRepo() returning false");
7066
+ return false;
7067
+ }
7068
+ async getRepoBlameRanges(_ref, _path) {
7069
+ console.warn("getRepoBlameRanges() returning empty array");
7070
+ return [];
7071
+ }
7072
+ async getReferenceData(_ref) {
7073
+ console.warn("getReferenceData() returning null/empty defaults");
7074
+ return {
7075
+ type: "BRANCH" /* BRANCH */,
7076
+ sha: "",
7077
+ date: void 0
7078
+ };
7079
+ }
7080
+ async getRepoDefaultBranch() {
7081
+ console.warn("getRepoDefaultBranch() returning empty string");
7082
+ return "";
7083
+ }
7084
+ async getSubmitRequestUrl(_submitRequestIdNumber) {
7085
+ console.warn("getSubmitRequestUrl() returning empty string");
7086
+ return "";
7087
+ }
7088
+ async getSubmitRequestId(_submitRequestUrl) {
7089
+ console.warn("getSubmitRequestId() returning empty string");
7090
+ return "";
7091
+ }
7092
+ async getCommitUrl(_commitId) {
7093
+ console.warn("getCommitUrl() returning empty string");
7094
+ return "";
7095
+ }
7096
+ async getBranchCommitsUrl(_branchName) {
7097
+ console.warn("getBranchCommitsUrl() returning empty string");
7098
+ return "";
7099
+ }
7100
+ async _getUsernameForAuthUrl() {
7101
+ console.warn("_getUsernameForAuthUrl() returning empty string");
7102
+ return "";
7103
+ }
7104
+ async addCommentToSubmitRequest(_submitRequestId, _comment) {
7105
+ console.warn("addCommentToSubmitRequest() no-op");
7106
+ }
7107
+ };
7108
+
7109
+ // src/features/analysis/scm/scmFactory.ts
7110
+ async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
7111
+ const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
7112
+ try {
7113
+ switch (scmType) {
7114
+ case "GITHUB" /* GITHUB */: {
7115
+ const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
7116
+ await scm.validateParams();
7117
+ return scm;
7118
+ }
7119
+ case "GITLAB" /* GITLAB */: {
7120
+ const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
7121
+ await scm.validateParams();
7122
+ return scm;
7123
+ }
7124
+ case "ADO" /* ADO */: {
7125
+ const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
7126
+ await scm.getAdoSdk();
7127
+ await scm.validateParams();
7128
+ return scm;
7129
+ }
7130
+ case "BITBUCKET" /* BITBUCKET */: {
7131
+ const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
7132
+ await scm.validateParams();
7133
+ return scm;
7134
+ }
7135
+ }
7136
+ } catch (e) {
7137
+ if (e instanceof InvalidRepoUrlError && url) {
7138
+ throw new RepoNoTokenAccessError(
7139
+ "no access to repo",
7140
+ scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
7141
+ );
7142
+ }
7143
+ console.error(`error validating scm: ${scmType} `, e);
7144
+ if (propagateExceptions) {
7145
+ throw e;
7146
+ }
7147
+ }
7148
+ return new StubSCMLib(trimmedUrl, void 0, void 0);
7149
+ }
7150
+
7151
+ // src/utils/index.ts
7152
+ var utils_exports = {};
7153
+ __export(utils_exports, {
7154
+ CliError: () => CliError,
7155
+ Spinner: () => Spinner,
7156
+ getDirName: () => getDirName,
7157
+ getTopLevelDirName: () => getTopLevelDirName,
7158
+ keypress: () => keypress,
7159
+ packageJson: () => packageJson,
7160
+ sleep: () => sleep
7161
+ });
7162
+
7163
+ // src/utils/dirname.ts
7164
+ import path from "node:path";
7165
+ import { fileURLToPath } from "node:url";
7166
+ function getDirName() {
7167
+ return path.dirname(fileURLToPath(import.meta.url));
7168
+ }
7169
+ function getTopLevelDirName(fullPath) {
7170
+ return path.parse(fullPath).name;
7171
+ }
7172
+
7173
+ // src/utils/keypress.ts
7174
+ import readline from "node:readline";
7175
+ async function keypress() {
7176
+ const rl = readline.createInterface({
7177
+ input: process.stdin,
7178
+ output: process.stdout
7179
+ });
7180
+ return new Promise((resolve) => {
7181
+ rl.question("", (answer) => {
7182
+ rl.close();
7183
+ process.stderr.moveCursor(0, -1);
7184
+ process.stderr.clearLine(1);
7185
+ resolve(answer);
7186
+ });
7187
+ });
7188
+ }
7189
+
7190
+ // src/utils/spinner.ts
7191
+ import {
7192
+ createSpinner as _createSpinner
7193
+ } from "nanospinner";
7194
+ function printToStdError(opts) {
7195
+ if (opts?.text) console.error(opts.text);
7196
+ }
7197
+ var mockSpinner = {
7198
+ success: (opts) => {
7199
+ printToStdError(opts);
7200
+ return mockSpinner;
7201
+ },
7202
+ error: (opts) => {
7203
+ printToStdError(opts);
7204
+ return mockSpinner;
7205
+ },
7206
+ warn: (opts) => {
7207
+ printToStdError(opts);
7208
+ return mockSpinner;
7209
+ },
7210
+ stop: (opts) => {
7211
+ printToStdError(opts);
7212
+ return mockSpinner;
7213
+ },
7214
+ start: (opts) => {
7215
+ printToStdError(opts);
7216
+ return mockSpinner;
7217
+ },
7218
+ update: (opts) => {
7219
+ printToStdError(opts);
7220
+ return mockSpinner;
7221
+ },
7222
+ reset: () => mockSpinner,
7223
+ clear: () => mockSpinner,
7224
+ spin: () => mockSpinner
7225
+ };
7226
+ function Spinner({ ci = false } = {}) {
7227
+ return {
7228
+ createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
7229
+ };
7230
+ }
7231
+
7232
+ // src/utils/check_node_version.ts
7233
+ import fs2 from "node:fs";
7234
+ import path2 from "node:path";
7235
+ import semver from "semver";
7236
+ function getPackageJson() {
7237
+ let manifestPath = path2.join(getDirName(), "../package.json");
7238
+ if (!fs2.existsSync(manifestPath)) {
7239
+ manifestPath = path2.join(getDirName(), "../../package.json");
7240
+ }
7241
+ return JSON.parse(fs2.readFileSync(manifestPath, "utf8"));
7242
+ }
7243
+ var packageJson = getPackageJson();
7244
+ if (!semver.satisfies(process.version, packageJson.engines.node)) {
7245
+ console.error(
7246
+ `
7247
+ \u26A0\uFE0F ${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
7248
+ );
7249
+ process.exit(1);
7250
+ }
7251
+
7252
+ // src/utils/index.ts
7253
+ var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
7254
+ var CliError = class extends Error {
7255
+ };
7256
+
7257
+ // src/commands/convert_to_sarif.ts
7258
+ import AdmZip from "adm-zip";
7259
+ import multimatch from "multimatch";
7260
+ import tmp from "tmp";
7261
+ async function convertToSarif(options) {
7262
+ switch (options.inputFileFormat) {
7263
+ case "FortifyFPR" /* FortifyFPR */:
7264
+ await convertFprToSarif(
7265
+ options.inputFilePath,
7266
+ options.outputFilePath,
7267
+ options.codePathPatterns ?? ["**", "*"]
7268
+ );
7269
+ break;
7270
+ }
7271
+ }
7272
+ async function convertFprToSarif(inputFilePath, outputFilePath, codePathPatterns) {
7273
+ const zipIn = new AdmZip(inputFilePath);
7274
+ if (!zipIn.getEntry("audit.fvdl")) {
7275
+ throw new CliError(
7276
+ "\nError: the input file should be in a valid Fortify FPR format."
7277
+ );
7278
+ }
7279
+ const tmpObj = tmp.dirSync({
7280
+ unsafeCleanup: true
7281
+ });
7282
+ try {
7283
+ zipIn.extractEntryTo("audit.fvdl", tmpObj.name);
7284
+ const auditFvdlSaxParser = initSaxParser(
7285
+ path3.join(tmpObj.name, "audit.fvdl")
7286
+ );
7287
+ const vulnerabilityParser = new VulnerabilityParser(
7288
+ auditFvdlSaxParser.parser
7289
+ );
7290
+ const unifiedNodePoolParser = new UnifiedNodePoolParser(
7291
+ auditFvdlSaxParser.parser
7292
+ );
7293
+ const reportMetadataParser = new ReportMetadataParser(
7294
+ auditFvdlSaxParser.parser
7295
+ );
7296
+ let auditMetadataParser = null;
7297
+ await auditFvdlSaxParser.parse();
7298
+ if (zipIn.getEntry("audit.xml")) {
7299
+ zipIn.extractEntryTo("audit.xml", tmpObj.name);
7300
+ const auditXmlSaxParser = initSaxParser(
7301
+ path3.join(tmpObj.name, "audit.xml")
7302
+ );
7303
+ auditMetadataParser = new AuditMetadataParser(auditXmlSaxParser.parser);
7304
+ await auditXmlSaxParser.parse();
7305
+ }
7306
+ fs3.writeFileSync(
7307
+ outputFilePath,
7308
+ `{
7309
+ "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
7310
+ "version": "2.1.0",
7311
+ "runs": [
7312
+ {
7313
+ "tool": {
7314
+ "driver": {
7315
+ "name": "Fortify Mobb Converter"
7316
+ }
7317
+ },
7318
+ "results": [
7319
+ `
7320
+ );
7321
+ vulnerabilityParser.getVulnerabilities().map(
7322
+ (vulnerability) => fortifyVulnerabilityToSarifResult(
7323
+ vulnerability,
7324
+ auditMetadataParser,
7325
+ reportMetadataParser,
7326
+ unifiedNodePoolParser
7327
+ )
7328
+ ).filter((sarifResult) => filterSarifResult(sarifResult, codePathPatterns)).forEach((sarifResult, index) => {
7329
+ fs3.appendFileSync(outputFilePath, JSON.stringify(sarifResult, null, 2));
7330
+ if (index !== vulnerabilityParser.getVulnerabilities().length - 1) {
7331
+ fs3.appendFileSync(outputFilePath, ",\n");
7332
+ }
7333
+ });
7334
+ fs3.appendFileSync(outputFilePath, "\n]}]}");
7335
+ } finally {
7336
+ tmpObj.removeCallback();
7337
+ }
7338
+ }
7339
+ function filterSarifResult(sarifResult, codePathPatterns) {
7340
+ const paths = sarifResult.locations.map(
7341
+ (l) => l.physicalLocation.artifactLocation.uri
7342
+ );
7343
+ const matchPaths = multimatch(paths, codePathPatterns, {
7344
+ dot: true
7345
+ });
7346
+ return matchPaths.length > 0;
7347
+ }
7348
+ function fortifyVulnerabilityToSarifResult(vulnerability, auditMetadataParser, reportMetadataParser, unifiedNodePoolParser) {
7349
+ const suppressed = auditMetadataParser?.getAuditMetadata()[vulnerability.instanceID] || "false";
7350
+ const ruleMeta = reportMetadataParser.getReportMetadata().rules[vulnerability.classID] ?? {};
7351
+ return {
7352
+ ruleId: vulnerability.type + (vulnerability.subtype ? `: ${vulnerability.subtype}` : ""),
7353
+ properties: {
7354
+ package: ruleMeta["package"] ?? "",
7355
+ probability: vulnerability.metaInfo["Probability"] ?? ruleMeta["Probability"] ?? "",
7356
+ impact: vulnerability.metaInfo["Impact"] ?? ruleMeta["Impact"] ?? "",
7357
+ accuracy: vulnerability.metaInfo["Accuracy"] ?? ruleMeta["Accuracy"] ?? "",
7358
+ confidence: vulnerability.confidence,
7359
+ instanceID: vulnerability.instanceID,
7360
+ instanceSeverity: vulnerability.instanceSeverity,
7361
+ suppressed
7362
+ },
7363
+ locations: fortifyNodesToSarifLocations(
7364
+ vulnerability.nodes,
7365
+ unifiedNodePoolParser
7366
+ ),
7367
+ message: {
7368
+ text: "no message"
7369
+ }
7370
+ };
7371
+ }
7372
+ function fortifyNodesToSarifLocations(nodes, unifiedNodePoolParser) {
7373
+ return nodes.map((node) => {
7374
+ let sourceLocation;
7375
+ if ("id" in node) {
7376
+ const poolNode = unifiedNodePoolParser.getNodesPull()[node.id];
7377
+ if (poolNode) {
7378
+ sourceLocation = poolNode;
7379
+ } else {
7380
+ throw new CliError(
7381
+ "\nError: the input file should be in a valid Fortify FPR format (broken unified node pool)."
7382
+ );
7383
+ }
7384
+ } else {
7385
+ sourceLocation = node;
7386
+ }
7387
+ return {
7388
+ physicalLocation: {
7389
+ artifactLocation: {
7390
+ uri: sourceLocation.path
7391
+ },
7392
+ region: {
7393
+ startLine: parseInt(sourceLocation.line || "0", 10),
7394
+ endLine: sourceLocation.lineEnd ? parseInt(sourceLocation.lineEnd, 10) : void 0,
7395
+ startColumn: parseInt(sourceLocation.colStart || "0", 10),
7396
+ endColumn: sourceLocation.colEnd ? parseInt(sourceLocation.colEnd, 10) : void 0
7397
+ }
7398
+ }
7399
+ };
7400
+ });
7401
+ }
7402
+
7403
+ // src/args/options.ts
7404
+ import chalk2 from "chalk";
7405
+
7406
+ // src/constants.ts
7407
+ import path4 from "node:path";
7408
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
7409
+ import chalk from "chalk";
7410
+ import Debug4 from "debug";
7411
+ import * as dotenv from "dotenv";
7412
+ import { z as z24 } from "zod";
7413
+ var debug4 = Debug4("mobbdev:constants");
7414
+ var __dirname = path4.dirname(fileURLToPath2(import.meta.url));
7415
+ dotenv.config({ path: path4.join(__dirname, "../.env") });
7416
+ var scmFriendlyText = {
7417
+ ["Ado" /* Ado */]: "Azure DevOps",
7418
+ ["Bitbucket" /* Bitbucket */]: "Bitbucket",
7419
+ ["GitHub" /* GitHub */]: "GitGub",
7420
+ ["GitLab" /* GitLab */]: "GitLab"
7421
+ };
7422
+ var SCANNERS = {
7423
+ Checkmarx: "checkmarx",
7424
+ Codeql: "codeql",
7425
+ Fortify: "fortify",
7426
+ Snyk: "snyk",
7427
+ Sonarqube: "sonarqube",
7428
+ Semgrep: "semgrep",
7429
+ Datadog: "datadog"
7430
+ };
7431
+ var scannerToVulnerability_Report_Vendor_Enum = {
7432
+ [SCANNERS.Checkmarx]: "checkmarx" /* Checkmarx */,
7433
+ [SCANNERS.Snyk]: "snyk" /* Snyk */,
7434
+ [SCANNERS.Sonarqube]: "sonarqube" /* Sonarqube */,
7435
+ [SCANNERS.Codeql]: "codeql" /* Codeql */,
7436
+ [SCANNERS.Fortify]: "fortify" /* Fortify */,
7437
+ [SCANNERS.Semgrep]: "semgrep" /* Semgrep */,
7438
+ [SCANNERS.Datadog]: "datadog" /* Datadog */
7439
+ };
7440
+ var SupportedScannersZ = z24.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
7441
+ var envVariablesSchema = z24.object({
7442
+ WEB_APP_URL: z24.string(),
7443
+ API_URL: z24.string(),
7444
+ HASURA_ACCESS_KEY: z24.string(),
7445
+ LOCAL_GRAPHQL_ENDPOINT: z24.string(),
7446
+ HTTP_PROXY: z24.string().optional().default(""),
7447
+ HTTPS_PROXY: z24.string().optional().default("")
7448
+ }).required();
7449
+ var envVariables = envVariablesSchema.parse(process.env);
7450
+ debug4("config %o", envVariables);
7451
+ var mobbAscii = `
7452
+ ..
7453
+ ..........
7454
+ .................
7455
+ ...........................
7456
+ ..............................
7457
+ ................................
7458
+ ..................................
7459
+ ....................................
7460
+ .....................................
7461
+ .............................................
7462
+ .................................................
7463
+ ............................... .................
7464
+ .................................. ............
7465
+ .................. ............. ..........
7466
+ ......... ........ ......... ......
7467
+ ............... ....
7468
+ .... ..
7469
+
7470
+ . ...
7471
+ ..............
7472
+ ......................
7473
+ ...........................
7474
+ ................................
7475
+ ......................................
7476
+ ...............................
7477
+ .................
7478
+ `;
7479
+ var PROJECT_DEFAULT_NAME = "My first project";
7480
+ var WEB_APP_URL = envVariables.WEB_APP_URL;
7481
+ var API_URL = envVariables.API_URL;
7482
+ var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
7483
+ var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
7484
+ var HTTPS_PROXY = envVariables.HTTPS_PROXY;
7485
+ var HTTP_PROXY = envVariables.HTTP_PROXY;
7486
+ var errorMessages = {
7487
+ missingCxProjectName: `project name ${chalk.bold(
7488
+ "(--cx-project-name)"
7489
+ )} is needed if you're using checkmarx`,
7490
+ missingUrl: `url ${chalk.bold(
7491
+ "(--url)"
7492
+ )} is needed if you're adding an SCM token`,
7493
+ invalidScmType: `SCM type ${chalk.bold(
7494
+ "(--scm-type)"
7495
+ )} is invalid, please use one of: ${Object.values(ScmType).join(", ")}`,
7496
+ missingToken: `SCM token ${chalk.bold(
7497
+ "(--token)"
7498
+ )} is needed if you're adding an SCM token`
7499
+ };
7500
+ var progressMassages = {
7501
+ processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
7502
+ processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
7503
+ processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
7504
+ };
7505
+ var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
7506
+
7507
+ // src/args/options.ts
7508
+ var repoOption = {
7509
+ alias: "r",
7510
+ demandOption: true,
7511
+ type: "string",
7512
+ describe: chalk2.bold("Github / GitLab / Azure DevOps repository URL")
7513
+ };
7514
+ var projectNameOption = {
7515
+ type: "string",
7516
+ describe: chalk2.bold("Checkmarx project name (when scanning with Checkmarx)")
7517
+ };
7518
+ var yesOption = {
7519
+ alias: "yes",
7520
+ type: "boolean",
7521
+ describe: chalk2.bold("Skip prompts and use default values")
7522
+ };
7523
+ var refOption = {
7524
+ describe: chalk2.bold("Reference of the repository (branch, tag, commit)"),
7525
+ type: "string",
7526
+ demandOption: false
7527
+ };
7528
+ var organizationIdOptions = {
7529
+ describe: chalk2.bold("Organization id"),
7530
+ alias: "organization-id",
7531
+ type: "string",
7532
+ demandOption: false
7533
+ };
7534
+ var scannerOptions = {
7535
+ alias: "s",
7536
+ choices: Object.values(SCANNERS),
7537
+ describe: chalk2.bold("Select the scanner to use")
7538
+ };
7539
+ var mobbProjectNameOption = {
7540
+ type: "string",
7541
+ describe: chalk2.bold("Mobb project name"),
7542
+ default: PROJECT_DEFAULT_NAME
7543
+ };
7544
+ var ciOption = {
7545
+ describe: chalk2.bold(
7546
+ "Run in CI mode, prompts and browser will not be opened"
7547
+ ),
7548
+ type: "boolean",
7549
+ default: false
7550
+ };
7551
+ var apiKeyOption = {
7552
+ type: "string",
7553
+ describe: chalk2.bold("Mobb authentication api-key")
7554
+ };
7555
+ var commitHashOption = {
7556
+ alias: "ch",
7557
+ describe: chalk2.bold("Hash of the commit"),
7558
+ type: "string"
7559
+ };
7560
+ var autoPrOption = {
7561
+ describe: chalk2.bold("Enable automatic pull requests for new fixes"),
7562
+ type: "boolean",
7563
+ default: false
7564
+ };
7565
+ var commitDirectlyOption = {
7566
+ describe: chalk2.bold(
7567
+ "Commit directly to the scanned branch instead of creating a pull request"
7568
+ ),
7569
+ type: "boolean",
7570
+ default: false
7571
+ };
7572
+ var scmTypeOption = {
7573
+ demandOption: true,
7574
+ describe: chalk2.bold("SCM type"),
7575
+ choices: Object.values(ScmType)
7576
+ };
7577
+ var urlOption = {
7578
+ describe: chalk2.bold(
7579
+ `URL of the repository (used in ${Object.values(ScmType).join(", ")})`
7580
+ ),
7581
+ type: "string",
7582
+ demandOption: true
7583
+ };
7584
+ var scmOrgOption = {
7585
+ describe: chalk2.bold("Organization name in SCM (used in Azure DevOps)"),
7586
+ type: "string"
7587
+ };
7588
+ var scmRefreshTokenOption = {
7589
+ describe: chalk2.bold("SCM refresh token (used in GitLab)"),
7590
+ type: "string"
7591
+ };
7592
+ var scmTokenOption = {
7593
+ describe: chalk2.bold("SCM API token"),
7594
+ type: "string",
7595
+ demandOption: true
7596
+ };
7597
+ var convertToSarifInputFilePathOption = {
7598
+ demandOption: true,
7599
+ describe: chalk2.bold("Original SAST report file path"),
7600
+ type: "string"
7601
+ };
7602
+ var convertToSarifOutputFilePathOption = {
7603
+ demandOption: true,
7604
+ describe: chalk2.bold("Output SARIF report file path"),
7605
+ type: "string"
7606
+ };
7607
+ var convertToSarifInputFileFormatOption = {
7608
+ demandOption: true,
7609
+ choices: Object.values(ConvertToSarifInputFileFormat),
7610
+ describe: chalk2.bold("SAST report file type")
6989
7611
  };
6990
-
6991
- // src/features/analysis/scm/scmFactory.ts
6992
- import { z as z24 } from "zod";
6993
-
6994
- // src/features/analysis/scm/StubSCMLib.ts
6995
- var StubSCMLib = class extends SCMLib {
6996
- constructor(url, accessToken, scmOrg) {
6997
- super(url, accessToken, scmOrg);
6998
- }
6999
- async getUrlWithCredentials() {
7000
- console.warn("getUrlWithCredentials() returning empty string");
7001
- return "";
7002
- }
7003
- async createSubmitRequest(_params) {
7004
- console.warn("createSubmitRequest() returning empty string");
7005
- return "";
7006
- }
7007
- get scmLibType() {
7008
- console.warn("scmLibType returning GITHUB as default");
7009
- return "GITHUB" /* GITHUB */;
7010
- }
7011
- getAuthHeaders() {
7012
- console.warn("getAuthHeaders() returning empty object");
7013
- return {};
7014
- }
7015
- async getDownloadUrl(_sha) {
7016
- console.warn("getDownloadUrl() returning empty string");
7017
- return "";
7018
- }
7019
- async getIsRemoteBranch(_branch) {
7020
- console.warn("getIsRemoteBranch() returning false");
7021
- return false;
7022
- }
7023
- async validateParams() {
7024
- console.warn("validateParams() no-op");
7025
- }
7026
- async getRepoList(_scmOrg) {
7027
- console.warn("getRepoList() returning empty array");
7028
- return [];
7029
- }
7030
- async getBranchList() {
7031
- console.warn("getBranchList() returning empty array");
7032
- return [];
7033
- }
7034
- async getUsername() {
7035
- console.warn("getUsername() returning empty string");
7036
- return "";
7037
- }
7038
- async getSubmitRequestStatus(_scmSubmitRequestId) {
7039
- console.warn("getSubmitRequestStatus() returning ERROR");
7040
- return "error";
7041
- }
7042
- async getUserHasAccessToRepo() {
7043
- console.warn("getUserHasAccessToRepo() returning false");
7044
- return false;
7045
- }
7046
- async getRepoBlameRanges(_ref, _path) {
7047
- console.warn("getRepoBlameRanges() returning empty array");
7048
- return [];
7049
- }
7050
- async getReferenceData(_ref) {
7051
- console.warn("getReferenceData() returning null/empty defaults");
7052
- return {
7053
- type: "BRANCH" /* BRANCH */,
7054
- sha: "",
7055
- date: void 0
7056
- };
7057
- }
7058
- async getRepoDefaultBranch() {
7059
- console.warn("getRepoDefaultBranch() returning empty string");
7060
- return "";
7061
- }
7062
- async getSubmitRequestUrl(_submitRequestIdNumber) {
7063
- console.warn("getSubmitRequestUrl() returning empty string");
7064
- return "";
7065
- }
7066
- async getSubmitRequestId(_submitRequestUrl) {
7067
- console.warn("getSubmitRequestId() returning empty string");
7068
- return "";
7069
- }
7070
- async getCommitUrl(_commitId) {
7071
- console.warn("getCommitUrl() returning empty string");
7072
- return "";
7073
- }
7074
- async _getUsernameForAuthUrl() {
7075
- console.warn("_getUsernameForAuthUrl() returning empty string");
7076
- return "";
7077
- }
7078
- async addCommentToSubmitRequest(_submitRequestId, _comment) {
7079
- console.warn("addCommentToSubmitRequest() no-op");
7080
- }
7612
+ var convertToSarifCodePathPatternsOption = {
7613
+ demandOption: false,
7614
+ describe: chalk2.bold(
7615
+ "Glob-like patterns. Any code node with this pattern makes the issue be included."
7616
+ ),
7617
+ type: "string",
7618
+ array: true
7081
7619
  };
7082
7620
 
7083
- // src/features/analysis/scm/scmFactory.ts
7084
- async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
7085
- const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
7086
- try {
7087
- switch (scmType) {
7088
- case "GITHUB" /* GITHUB */: {
7089
- const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
7090
- await scm.validateParams();
7091
- return scm;
7092
- }
7093
- case "GITLAB" /* GITLAB */: {
7094
- const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
7095
- await scm.validateParams();
7096
- return scm;
7097
- }
7098
- case "ADO" /* ADO */: {
7099
- const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
7100
- await scm.getAdoSdk();
7101
- await scm.validateParams();
7102
- return scm;
7103
- }
7104
- case "BITBUCKET" /* BITBUCKET */: {
7105
- const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
7106
- await scm.validateParams();
7107
- return scm;
7108
- }
7109
- }
7110
- } catch (e) {
7111
- if (e instanceof InvalidRepoUrlError && url) {
7112
- throw new RepoNoTokenAccessError(
7113
- "no access to repo",
7114
- scmLibScmTypeToScmType[z24.nativeEnum(ScmLibScmType).parse(scmType)]
7115
- );
7116
- }
7117
- console.error(`error validating scm: ${scmType} `, e);
7118
- if (propagateExceptions) {
7119
- throw e;
7120
- }
7621
+ // src/args/commands/convert_to_sarif.ts
7622
+ function convertToSarifBuilder(args) {
7623
+ return args.option("input-file-path", convertToSarifInputFilePathOption).option("input-file-format", convertToSarifInputFileFormatOption).option("output-file-path", convertToSarifOutputFilePathOption).option("code-path-patterns", convertToSarifCodePathPatternsOption).example(
7624
+ "npx mobbdev@latest convert-to-sarif --input-file-path /path/to/vuln-report.fpr --input-file-format FortifyFPR --output-file-path /path/to/vuln-report.sarif --code-path-patterns **/*.ts --code-path-patterns **/*.js",
7625
+ "convert an existing SAST report to SARIF format"
7626
+ ).help().demandOption(["input-file-path", "input-file-format", "output-file-path"]);
7627
+ }
7628
+ async function validateConvertToSarifOptions(args) {
7629
+ if (!fs4.existsSync(args.inputFilePath)) {
7630
+ throw new CliError(
7631
+ "\nError: --input-file-path flag should point to an existing file"
7632
+ );
7121
7633
  }
7122
- return new StubSCMLib(trimmedUrl, void 0, void 0);
7123
7634
  }
7635
+ async function convertToSarifHandler(args) {
7636
+ await validateConvertToSarifOptions(args);
7637
+ await convertToSarif(args);
7638
+ }
7639
+
7640
+ // src/types.ts
7641
+ var mobbCliCommand = {
7642
+ addScmToken: "add-scm-token",
7643
+ scan: "scan",
7644
+ analyze: "analyze",
7645
+ review: "review",
7646
+ convertToSarif: "convert-to-sarif"
7647
+ };
7648
+
7649
+ // src/args/yargs.ts
7650
+ import chalk10 from "chalk";
7651
+ import yargs from "yargs/yargs";
7652
+
7653
+ // src/args/commands/analyze.ts
7654
+ import fs7 from "node:fs";
7655
+
7656
+ // src/commands/index.ts
7657
+ import crypto from "node:crypto";
7658
+ import os from "node:os";
7659
+
7660
+ // src/features/analysis/index.ts
7661
+ import fs6 from "node:fs";
7662
+ import fsPromises from "node:fs/promises";
7663
+ import path7 from "node:path";
7664
+ import { env as env2 } from "node:process";
7665
+ import { pipeline } from "node:stream/promises";
7666
+ import chalk5 from "chalk";
7667
+ import Configstore from "configstore";
7668
+ import Debug18 from "debug";
7669
+ import extract from "extract-zip";
7670
+ import { createSpinner as createSpinner4 } from "nanospinner";
7671
+ import fetch4 from "node-fetch";
7672
+ import open2 from "open";
7673
+ import tmp2 from "tmp";
7674
+ import { z as z29 } from "zod";
7675
+
7676
+ // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
7677
+ import Debug8 from "debug";
7124
7678
 
7125
7679
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
7126
7680
  import Debug7 from "debug";
@@ -7390,7 +7944,7 @@ async function postIssueComment(params) {
7390
7944
  fpDescription
7391
7945
  } = params;
7392
7946
  const {
7393
- path: path8,
7947
+ path: path9,
7394
7948
  startLine,
7395
7949
  vulnerabilityReportIssue: {
7396
7950
  vulnerabilityReportIssueTags,
@@ -7405,7 +7959,7 @@ async function postIssueComment(params) {
7405
7959
  Refresh the page in order to see the changes.`,
7406
7960
  pull_number: pullRequest,
7407
7961
  commit_id: commitSha,
7408
- path: path8,
7962
+ path: path9,
7409
7963
  line: startLine
7410
7964
  });
7411
7965
  const commentId = commentRes.data.id;
@@ -7439,7 +7993,7 @@ async function postFixComment(params) {
7439
7993
  scanner
7440
7994
  } = params;
7441
7995
  const {
7442
- path: path8,
7996
+ path: path9,
7443
7997
  startLine,
7444
7998
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
7445
7999
  vulnerabilityReportIssueId
@@ -7457,7 +8011,7 @@ async function postFixComment(params) {
7457
8011
  Refresh the page in order to see the changes.`,
7458
8012
  pull_number: pullRequest,
7459
8013
  commit_id: commitSha,
7460
- path: path8,
8014
+ path: path9,
7461
8015
  line: startLine
7462
8016
  });
7463
8017
  const commentId = commentRes.data.id;
@@ -8275,9 +8829,9 @@ var GQLClient = class {
8275
8829
  };
8276
8830
 
8277
8831
  // src/features/analysis/pack.ts
8278
- import fs2 from "node:fs";
8279
- import path4 from "node:path";
8280
- import AdmZip from "adm-zip";
8832
+ import fs5 from "node:fs";
8833
+ import path5 from "node:path";
8834
+ import AdmZip2 from "adm-zip";
8281
8835
  import Debug13 from "debug";
8282
8836
  import { globby } from "globby";
8283
8837
  import { isBinary } from "istextorbinary";
@@ -8339,23 +8893,23 @@ async function pack(srcDirPath, vulnFiles) {
8339
8893
  dot: true
8340
8894
  });
8341
8895
  debug13("files found %d", filepaths.length);
8342
- const zip = new AdmZip();
8896
+ const zip = new AdmZip2();
8343
8897
  debug13("compressing files");
8344
8898
  for (const filepath of filepaths) {
8345
- const absFilepath = path4.join(srcDirPath, filepath.toString());
8899
+ const absFilepath = path5.join(srcDirPath, filepath.toString());
8346
8900
  vulnFiles = vulnFiles.concat(_get_manifest_files_suffixes());
8347
8901
  if (!endsWithAny(
8348
- absFilepath.toString().replaceAll(path4.win32.sep, path4.posix.sep),
8902
+ absFilepath.toString().replaceAll(path5.win32.sep, path5.posix.sep),
8349
8903
  vulnFiles
8350
8904
  )) {
8351
8905
  debug13("ignoring %s because it is not a vulnerability file", filepath);
8352
8906
  continue;
8353
8907
  }
8354
- if (fs2.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
8908
+ if (fs5.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
8355
8909
  debug13("ignoring %s because the size is > 5MB", filepath);
8356
8910
  continue;
8357
8911
  }
8358
- const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs2.readFileSync(absFilepath);
8912
+ const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs5.readFileSync(absFilepath);
8359
8913
  if (isBinary(null, data)) {
8360
8914
  debug13("ignoring %s because is seems to be a binary file", filepath);
8361
8915
  continue;
@@ -8367,8 +8921,8 @@ async function pack(srcDirPath, vulnFiles) {
8367
8921
  }
8368
8922
  async function repackFpr(fprPath) {
8369
8923
  debug13("repack fpr file %s", fprPath);
8370
- const zipIn = new AdmZip(fprPath);
8371
- const zipOut = new AdmZip();
8924
+ const zipIn = new AdmZip2(fprPath);
8925
+ const zipOut = new AdmZip2();
8372
8926
  const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
8373
8927
  const filesMapping = FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA.parse(
8374
8928
  await parseStringPromise(mappingXML)
@@ -8507,12 +9061,12 @@ function createChildProcess({ childProcess, name }, options) {
8507
9061
  }
8508
9062
 
8509
9063
  // src/features/analysis/scanners/checkmarx.ts
8510
- import chalk2 from "chalk";
9064
+ import chalk3 from "chalk";
8511
9065
  import Debug15 from "debug";
8512
9066
  import { existsSync } from "fs";
8513
9067
  import { createSpinner as createSpinner2 } from "nanospinner";
8514
9068
  import { type } from "os";
8515
- import path5 from "path";
9069
+ import path6 from "path";
8516
9070
  var debug14 = Debug15("mobbdev:checkmarx");
8517
9071
  var require2 = createRequire(import.meta.url);
8518
9072
  var getCheckmarxPath = () => {
@@ -8572,9 +9126,9 @@ async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectN
8572
9126
  await startCheckmarxConfigationPrompt();
8573
9127
  await validateCheckamxCredentials();
8574
9128
  }
8575
- const extension = path5.extname(reportPath);
8576
- const filePath = path5.dirname(reportPath);
8577
- const fileName = path5.basename(reportPath, extension);
9129
+ const extension = path6.extname(reportPath);
9130
+ const filePath = path6.dirname(reportPath);
9131
+ const fileName = path6.basename(reportPath, extension);
8578
9132
  const checkmarxCommandArgs = getCheckmarxCommandArgs({
8579
9133
  repoPath: repositoryRoot,
8580
9134
  branch,
@@ -8600,7 +9154,7 @@ async function throwCheckmarxConfigError() {
8600
9154
  await createSpinner2("\u{1F513} Checkmarx is not configued correctly").start().error();
8601
9155
  throw new CliError(
8602
9156
  `Checkmarx is not configued correctly
8603
- you can configure it by using the ${chalk2.bold(
9157
+ you can configure it by using the ${chalk3.bold(
8604
9158
  "cx configure"
8605
9159
  )} command`
8606
9160
  );
@@ -8608,8 +9162,8 @@ async function throwCheckmarxConfigError() {
8608
9162
  async function validateCheckamxCredentials() {
8609
9163
  console.log(`
8610
9164
  Here's a suggestion for checkmarx configuation:
8611
- ${chalk2.bold("AST Base URI:")} https://ast.checkmarx.net
8612
- ${chalk2.bold("AST Base Auth URI (IAM):")} https://iam.checkmarx.net
9165
+ ${chalk3.bold("AST Base URI:")} https://ast.checkmarx.net
9166
+ ${chalk3.bold("AST Base Auth URI (IAM):")} https://iam.checkmarx.net
8613
9167
  `);
8614
9168
  await forkCheckmarx(CONFIGURE_COMMAND, { display: true });
8615
9169
  const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
@@ -8628,7 +9182,7 @@ async function validateCheckamxCredentials() {
8628
9182
 
8629
9183
  // src/features/analysis/scanners/snyk.ts
8630
9184
  import { createRequire as createRequire2 } from "node:module";
8631
- import chalk3 from "chalk";
9185
+ import chalk4 from "chalk";
8632
9186
  import Debug16 from "debug";
8633
9187
  import { createSpinner as createSpinner3 } from "nanospinner";
8634
9188
  import open from "open";
@@ -8675,7 +9229,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8675
9229
  await open(SNYK_ARTICLE_URL);
8676
9230
  }
8677
9231
  console.log(
8678
- chalk3.bgBlue(
9232
+ chalk4.bgBlue(
8679
9233
  "\nPlease enable Snyk Code in your Snyk account and try again."
8680
9234
  )
8681
9235
  );
@@ -8757,7 +9311,7 @@ async function downloadRepo({
8757
9311
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
8758
9312
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
8759
9313
  debug17("download repo %s %s %s", repoUrl, dirname);
8760
- const zipFilePath = path6.join(dirname, "repo.zip");
9314
+ const zipFilePath = path7.join(dirname, "repo.zip");
8761
9315
  debug17("download URL: %s auth headers: %o", downloadUrl, authHeaders);
8762
9316
  const response = await fetch4(downloadUrl, {
8763
9317
  method: "GET",
@@ -8768,21 +9322,21 @@ async function downloadRepo({
8768
9322
  if (!response.ok) {
8769
9323
  debug17("SCM zipball request failed %s %s", response.body, response.status);
8770
9324
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
8771
- throw new Error(`Can't access ${chalk4.bold(repoUrl)}`);
9325
+ throw new Error(`Can't access ${chalk5.bold(repoUrl)}`);
8772
9326
  }
8773
- const fileWriterStream = fs3.createWriteStream(zipFilePath);
9327
+ const fileWriterStream = fs6.createWriteStream(zipFilePath);
8774
9328
  if (!response.body) {
8775
9329
  throw new Error("Response body is empty");
8776
9330
  }
8777
9331
  await pipeline(response.body, fileWriterStream);
8778
9332
  await extract(zipFilePath, { dir: dirname });
8779
- const repoRoot = fs3.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
9333
+ const repoRoot = fs6.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
8780
9334
  if (!repoRoot) {
8781
9335
  throw new Error("Repo root not found");
8782
9336
  }
8783
9337
  debug17("repo root %s", repoRoot);
8784
9338
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
8785
- return path6.join(dirname, repoRoot);
9339
+ return path7.join(dirname, repoRoot);
8786
9340
  }
8787
9341
  var getReportUrl = ({
8788
9342
  organizationId,
@@ -8793,7 +9347,7 @@ var debug17 = Debug18("mobbdev:index");
8793
9347
  var config2 = new Configstore(packageJson.name, { apiToken: "" });
8794
9348
  debug17("config %o", config2);
8795
9349
  async function runAnalysis(params, options) {
8796
- const tmpObj = tmp.dirSync({
9350
+ const tmpObj = tmp2.dirSync({
8797
9351
  unsafeCleanup: true
8798
9352
  });
8799
9353
  try {
@@ -8892,7 +9446,7 @@ async function getReport(params, { skipPrompts }) {
8892
9446
  authHeaders: scm.getAuthHeaders(),
8893
9447
  downloadUrl
8894
9448
  });
8895
- const reportPath = path6.join(dirname, "report.json");
9449
+ const reportPath = path7.join(dirname, "report.json");
8896
9450
  switch (scanner) {
8897
9451
  case "snyk":
8898
9452
  await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
@@ -9099,11 +9653,11 @@ async function _scan(params, { skipPrompts = false } = {}) {
9099
9653
  fixReportId: reportUploadInfo.fixReportId
9100
9654
  });
9101
9655
  !ci && console.log("You can access the analysis at: \n");
9102
- console.log(chalk4.bold(reportUrl));
9656
+ console.log(chalk5.bold(reportUrl));
9103
9657
  !skipPrompts && await mobbAnalysisPrompt();
9104
9658
  !ci && open2(reportUrl);
9105
9659
  !ci && console.log(
9106
- chalk4.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
9660
+ chalk5.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
9107
9661
  );
9108
9662
  }
9109
9663
  async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
@@ -9180,7 +9734,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
9180
9734
  const zippingSpinner = createSpinner5("\u{1F4E6} Zipping repo").start();
9181
9735
  let zipBuffer;
9182
9736
  let gitInfo = { success: false };
9183
- if (srcFileStatus.isFile() && path6.extname(srcPath).toLowerCase() === ".fpr") {
9737
+ if (srcFileStatus.isFile() && path7.extname(srcPath).toLowerCase() === ".fpr") {
9184
9738
  zipBuffer = await repackFpr(srcPath);
9185
9739
  } else {
9186
9740
  gitInfo = await getGitInfo(srcPath);
@@ -9333,7 +9887,7 @@ async function waitForAnaysisAndReviewPr({
9333
9887
  }
9334
9888
 
9335
9889
  // src/commands/index.ts
9336
- import chalk5 from "chalk";
9890
+ import chalk6 from "chalk";
9337
9891
  import chalkAnimation from "chalk-animation";
9338
9892
  import Configstore2 from "configstore";
9339
9893
  import Debug19 from "debug";
@@ -9466,7 +10020,7 @@ async function showWelcomeMessage(skipPrompts = false) {
9466
10020
  var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
9467
10021
  var LOGIN_CHECK_DELAY = 5 * 1e3;
9468
10022
  var webLoginUrl = `${WEB_APP_URL}/cli-login`;
9469
- var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk5.bgBlue(
10023
+ var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk6.bgBlue(
9470
10024
  "press any key to continue"
9471
10025
  )};`;
9472
10026
  async function handleMobbLogin({
@@ -9560,101 +10114,9 @@ async function handleMobbLogin({
9560
10114
  // src/args/commands/analyze.ts
9561
10115
  import chalk8 from "chalk";
9562
10116
 
9563
- // src/args/options.ts
9564
- import chalk6 from "chalk";
9565
- var repoOption = {
9566
- alias: "r",
9567
- demandOption: true,
9568
- type: "string",
9569
- describe: chalk6.bold("Github / GitLab / Azure DevOps repository URL")
9570
- };
9571
- var projectNameOption = {
9572
- type: "string",
9573
- describe: chalk6.bold("Checkmarx project name (when scanning with Checkmarx)")
9574
- };
9575
- var yesOption = {
9576
- alias: "yes",
9577
- type: "boolean",
9578
- describe: chalk6.bold("Skip prompts and use default values")
9579
- };
9580
- var refOption = {
9581
- describe: chalk6.bold("Reference of the repository (branch, tag, commit)"),
9582
- type: "string",
9583
- demandOption: false
9584
- };
9585
- var organizationIdOptions = {
9586
- describe: chalk6.bold("Organization id"),
9587
- alias: "organization-id",
9588
- type: "string",
9589
- demandOption: false
9590
- };
9591
- var scannerOptions = {
9592
- alias: "s",
9593
- choices: Object.values(SCANNERS),
9594
- describe: chalk6.bold("Select the scanner to use")
9595
- };
9596
- var mobbProjectNameOption = {
9597
- type: "string",
9598
- describe: chalk6.bold("Mobb project name"),
9599
- default: PROJECT_DEFAULT_NAME
9600
- };
9601
- var ciOption = {
9602
- describe: chalk6.bold(
9603
- "Run in CI mode, prompts and browser will not be opened"
9604
- ),
9605
- type: "boolean",
9606
- default: false
9607
- };
9608
- var apiKeyOption = {
9609
- type: "string",
9610
- describe: chalk6.bold("Mobb authentication api-key")
9611
- };
9612
- var commitHashOption = {
9613
- alias: "ch",
9614
- describe: chalk6.bold("Hash of the commit"),
9615
- type: "string"
9616
- };
9617
- var autoPrOption = {
9618
- describe: chalk6.bold("Enable automatic pull requests for new fixes"),
9619
- type: "boolean",
9620
- default: false
9621
- };
9622
- var commitDirectlyOption = {
9623
- describe: chalk6.bold(
9624
- "Commit directly to the scanned branch instead of creating a pull request"
9625
- ),
9626
- type: "boolean",
9627
- default: false
9628
- };
9629
- var scmTypeOption = {
9630
- demandOption: true,
9631
- describe: chalk6.bold("SCM type"),
9632
- choices: Object.values(ScmType)
9633
- };
9634
- var urlOption = {
9635
- describe: chalk6.bold(
9636
- `URL of the repository (used in ${Object.values(ScmType).join(", ")})`
9637
- ),
9638
- type: "string",
9639
- demandOption: true
9640
- };
9641
- var scmOrgOption = {
9642
- describe: chalk6.bold("Organization name in SCM (used in Azure DevOps)"),
9643
- type: "string"
9644
- };
9645
- var scmRefreshTokenOption = {
9646
- describe: chalk6.bold("SCM refresh token (used in GitLab)"),
9647
- type: "string"
9648
- };
9649
- var scmTokenOption = {
9650
- describe: chalk6.bold("SCM API token"),
9651
- type: "string",
9652
- demandOption: true
9653
- };
9654
-
9655
10117
  // src/args/validation.ts
9656
10118
  import chalk7 from "chalk";
9657
- import path7 from "path";
10119
+ import path8 from "path";
9658
10120
  import { z as z30 } from "zod";
9659
10121
  function throwRepoUrlErrorMessage({
9660
10122
  error,
@@ -9698,7 +10160,7 @@ function validateRepoUrl(args) {
9698
10160
  }
9699
10161
  var supportExtensions = [".json", ".xml", ".fpr", ".sarif"];
9700
10162
  function validateReportFileFormat(reportFile) {
9701
- if (!supportExtensions.includes(path7.extname(reportFile))) {
10163
+ if (!supportExtensions.includes(path8.extname(reportFile))) {
9702
10164
  throw new CliError(
9703
10165
  `
9704
10166
  ${chalk7.bold(
@@ -9741,7 +10203,7 @@ function analyzeBuilder(yargs2) {
9741
10203
  ).help();
9742
10204
  }
9743
10205
  function validateAnalyzeOptions(argv) {
9744
- if (!fs4.existsSync(argv.f)) {
10206
+ if (!fs7.existsSync(argv.f)) {
9745
10207
  throw new CliError(`
9746
10208
  Can't access ${chalk8.bold(argv.f)}`);
9747
10209
  }
@@ -9773,7 +10235,7 @@ async function analyzeHandler(args) {
9773
10235
  }
9774
10236
 
9775
10237
  // src/args/commands/review.ts
9776
- import fs5 from "node:fs";
10238
+ import fs8 from "node:fs";
9777
10239
  import chalk9 from "chalk";
9778
10240
  function reviewBuilder(yargs2) {
9779
10241
  return yargs2.option("f", {
@@ -9810,7 +10272,7 @@ function reviewBuilder(yargs2) {
9810
10272
  ).help();
9811
10273
  }
9812
10274
  function validateReviewOptions(argv) {
9813
- if (!fs5.existsSync(argv.f)) {
10275
+ if (!fs8.existsSync(argv.f)) {
9814
10276
  throw new CliError(`
9815
10277
  Can't access ${chalk9.bold(argv.f)}`);
9816
10278
  }
@@ -9926,6 +10388,11 @@ var parseArgs = async (args) => {
9926
10388
  ),
9927
10389
  addScmTokenBuilder,
9928
10390
  addScmTokenHandler
10391
+ ).command(
10392
+ mobbCliCommand.convertToSarif,
10393
+ chalk10.bold("Convert an existing SAST report to SARIF format."),
10394
+ convertToSarifBuilder,
10395
+ convertToSarifHandler
9929
10396
  ).example(
9930
10397
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
9931
10398
  "Scan an existing repository"