mobbdev 1.0.77 → 1.0.80

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 +1133 -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";
@@ -246,6 +469,7 @@ var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Ve
246
469
  Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
247
470
  Vulnerability_Report_Vendor_Enum3["Datadog"] = "datadog";
248
471
  Vulnerability_Report_Vendor_Enum3["Fortify"] = "fortify";
472
+ Vulnerability_Report_Vendor_Enum3["FortifyMobbSarif"] = "fortifyMobbSarif";
249
473
  Vulnerability_Report_Vendor_Enum3["Opengrep"] = "opengrep";
250
474
  Vulnerability_Report_Vendor_Enum3["Semgrep"] = "semgrep";
251
475
  Vulnerability_Report_Vendor_Enum3["Snyk"] = "snyk";
@@ -753,9 +977,6 @@ function getSdk(client, withWrapper = defaultWrapper) {
753
977
  };
754
978
  }
755
979
 
756
- // src/features/analysis/scm/shared/src/types/fix.ts
757
- import { z as z2 } from "zod";
758
-
759
980
  // src/features/analysis/scm/shared/src/types/shared.ts
760
981
  import { z } from "zod";
761
982
  var ParsedSeverityZ = z.nativeEnum(Vulnerability_Severity_Enum).nullish().transform((i) => i ?? "low" /* Low */);
@@ -1177,7 +1398,9 @@ var issueTypeMap = {
1177
1398
  ["RETURN_SHOULD_NOT_BE_INVARIANT" /* ReturnShouldNotBeInvariant */]: "Return Should Not Be Invariant",
1178
1399
  ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: "SystemExit Should Reraise",
1179
1400
  ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: "No Return in Finally Block",
1180
- ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types"
1401
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types",
1402
+ ["AVOID_BUILTIN_SHADOWING" /* AvoidBuiltinShadowing */]: "Avoid Builtin Shadowing",
1403
+ ["IMPROPER_STRING_FORMATTING" /* ImproperStringFormatting */]: "Improper String Formatting"
1181
1404
  };
1182
1405
  var issueTypeZ = z5.nativeEnum(IssueType_Enum);
1183
1406
  var getIssueTypeFriendlyString = (issueType) => {
@@ -1630,290 +1853,49 @@ var ScmType = /* @__PURE__ */ ((ScmType2) => {
1630
1853
  ScmType2["Bitbucket"] = "Bitbucket";
1631
1854
  return ScmType2;
1632
1855
  })(ScmType || {});
1856
+ var ConvertToSarifInputFileFormat = /* @__PURE__ */ ((ConvertToSarifInputFileFormat2) => {
1857
+ ConvertToSarifInputFileFormat2["FortifyFPR"] = "FortifyFPR";
1858
+ return ConvertToSarifInputFileFormat2;
1859
+ })(ConvertToSarifInputFileFormat || {});
1633
1860
 
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;
1861
+ // src/features/analysis/scm/ado/constants.ts
1862
+ var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
1728
1863
 
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";
1864
+ // src/features/analysis/scm/ado/utils.ts
1865
+ import querystring from "node:querystring";
1866
+ import * as api from "azure-devops-node-api";
1867
+ import Debug from "debug";
1868
+ import { z as z17 } from "zod";
1735
1869
 
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
1870
+ // src/features/analysis/scm/env.ts
1871
+ import { z as z8 } from "zod";
1872
+ var EnvVariablesZod = z8.object({
1873
+ GITLAB_API_TOKEN: z8.string().optional(),
1874
+ GITHUB_API_TOKEN: z8.string().optional(),
1875
+ GIT_PROXY_HOST: z8.string().optional().default("http://tinyproxy:8888")
1746
1876
  });
1877
+ var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
1747
1878
 
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
- }
1879
+ // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
1880
+ import { z as z9 } from "zod";
1774
1881
 
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;
1882
+ // src/features/analysis/scm/shared/src/fixDetailsData.ts
1883
+ var fixDetailsData = {
1884
+ ["PT" /* Pt */]: {
1885
+ 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.",
1886
+ fixInstructions: "Sanitize user-supplied paths, ensuring that they are restricted to a predefined directory structure."
1786
1887
  },
1787
- error: (opts) => {
1788
- printToStdError(opts);
1789
- return mockSpinner;
1888
+ ["ZIP_SLIP" /* ZipSlip */]: {
1889
+ 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.",
1890
+ fixInstructions: "Ensure that extracted files are relative and within the intended directory structure."
1790
1891
  },
1791
- warn: (opts) => {
1792
- printToStdError(opts);
1793
- return mockSpinner;
1892
+ ["XSS" /* Xss */]: {
1893
+ 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.",
1894
+ fixInstructions: "Implement input validation and output encoding. This includes sanitizing user input and escaping special characters to prevent execution of injected scripts."
1794
1895
  },
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."
1896
+ ["XXE" /* Xxe */]: {
1897
+ 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.",
1898
+ 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
1899
  },
1918
1900
  ["CMDi" /* CmDi */]: {
1919
1901
  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 +2129,9 @@ var fixDetailsData = {
2147
2129
  ["RETURN_SHOULD_NOT_BE_INVARIANT" /* ReturnShouldNotBeInvariant */]: void 0,
2148
2130
  ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: void 0,
2149
2131
  ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: void 0,
2150
- ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0
2132
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0,
2133
+ ["AVOID_BUILTIN_SHADOWING" /* AvoidBuiltinShadowing */]: void 0,
2134
+ ["IMPROPER_STRING_FORMATTING" /* ImproperStringFormatting */]: void 0
2151
2135
  };
2152
2136
 
2153
2137
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
@@ -2178,7 +2162,7 @@ var getCommitDescription = ({
2178
2162
  )}**.
2179
2163
 
2180
2164
  `;
2181
- const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2165
+ const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2182
2166
  if (issueType && parseIssueTypeRes.success) {
2183
2167
  if (irrelevantIssueWithTags?.[0]?.tag) {
2184
2168
  description += `
@@ -2221,7 +2205,7 @@ var getCommitIssueDescription = ({
2221
2205
  const issueTypeString = getIssueTypeFriendlyString(issueType);
2222
2206
  let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
2223
2207
  `;
2224
- const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2208
+ const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2225
2209
  if (issueType && parseIssueTypeRes.success) {
2226
2210
  if (irrelevantIssueWithTags?.[0]?.tag) {
2227
2211
  description = `
@@ -2246,10 +2230,10 @@ ${staticData.issueDescription}
2246
2230
  };
2247
2231
 
2248
2232
  // src/features/analysis/scm/shared/src/guidances.ts
2249
- import { z as z13 } from "zod";
2233
+ import { z as z12 } from "zod";
2250
2234
 
2251
2235
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2252
- import { z as z11 } from "zod";
2236
+ import { z as z10 } from "zod";
2253
2237
 
2254
2238
  // src/features/analysis/scm/shared/src/storedFixData/passwordInComment.ts
2255
2239
  var passwordInComment = {
@@ -2425,8 +2409,8 @@ var vulnerabilities8 = {
2425
2409
  var xml_default = vulnerabilities8;
2426
2410
 
2427
2411
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2428
- var StoredFixDataItemZ = z11.object({
2429
- guidance: z11.function().returns(z11.string())
2412
+ var StoredFixDataItemZ = z10.object({
2413
+ guidance: z10.function().returns(z10.string())
2430
2414
  });
2431
2415
  var languages = {
2432
2416
  ["Java" /* Java */]: java_default,
@@ -2440,7 +2424,7 @@ var languages = {
2440
2424
  };
2441
2425
 
2442
2426
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
2443
- import { z as z12 } from "zod";
2427
+ import { z as z11 } from "zod";
2444
2428
 
2445
2429
  // src/features/analysis/scm/shared/src/storedQuestionData/csharp/httpOnlyCookie.ts
2446
2430
  var httpOnlyCookie = {
@@ -3639,10 +3623,10 @@ var vulnerabilities14 = {
3639
3623
  var xml_default2 = vulnerabilities14;
3640
3624
 
3641
3625
  // 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())
3626
+ var StoredQuestionDataItemZ = z11.object({
3627
+ content: z11.function().args(z11.any()).returns(z11.string()),
3628
+ description: z11.function().args(z11.any()).returns(z11.string()),
3629
+ guidance: z11.function().args(z11.any()).returns(z11.string())
3646
3630
  });
3647
3631
  var languages2 = {
3648
3632
  ["Java" /* Java */]: java_default2,
@@ -3737,9 +3721,9 @@ function getFixGuidances({
3737
3721
  const fixGuidance = storeFixResult.success ? [storeFixResult.data.guidance({ questions, ...extraContext })] : [];
3738
3722
  return libGuidances.concat(fixGuidance).filter((guidance) => !!guidance);
3739
3723
  }
3740
- var IssueTypeAndLanguageZ = z13.object({
3741
- issueType: z13.nativeEnum(IssueType_Enum),
3742
- issueLanguage: z13.nativeEnum(IssueLanguage_Enum)
3724
+ var IssueTypeAndLanguageZ = z12.object({
3725
+ issueType: z12.nativeEnum(IssueType_Enum),
3726
+ issueLanguage: z12.nativeEnum(IssueLanguage_Enum)
3743
3727
  });
3744
3728
  function getGuidances(args) {
3745
3729
  const safeIssueTypeAndLanguage = IssueTypeAndLanguageZ.safeParse({
@@ -3777,7 +3761,7 @@ function getGuidances(args) {
3777
3761
  }
3778
3762
 
3779
3763
  // src/features/analysis/scm/shared/src/urlParser/urlParser.ts
3780
- import { z as z14 } from "zod";
3764
+ import { z as z13 } from "zod";
3781
3765
  var ADO_PREFIX_PATH = "tfs";
3782
3766
  var NAME_REGEX = /[a-z0-9\-_.+]+/i;
3783
3767
  function detectAdoUrl(args) {
@@ -3794,7 +3778,7 @@ function detectAdoUrl(args) {
3794
3778
  scmType: "Ado" /* Ado */,
3795
3779
  organization,
3796
3780
  // project has single repo - repoName === projectName
3797
- projectName: z14.string().parse(projectName),
3781
+ projectName: z13.string().parse(projectName),
3798
3782
  repoName: projectName,
3799
3783
  prefixPath
3800
3784
  };
@@ -3805,7 +3789,7 @@ function detectAdoUrl(args) {
3805
3789
  return {
3806
3790
  scmType: "Ado" /* Ado */,
3807
3791
  organization,
3808
- projectName: z14.string().parse(projectName),
3792
+ projectName: z13.string().parse(projectName),
3809
3793
  repoName,
3810
3794
  prefixPath
3811
3795
  };
@@ -3819,7 +3803,7 @@ function detectAdoUrl(args) {
3819
3803
  scmType: "Ado" /* Ado */,
3820
3804
  organization,
3821
3805
  // project has only one repo - repoName === projectName
3822
- projectName: z14.string().parse(repoName),
3806
+ projectName: z13.string().parse(repoName),
3823
3807
  repoName,
3824
3808
  prefixPath
3825
3809
  };
@@ -3829,7 +3813,7 @@ function detectAdoUrl(args) {
3829
3813
  return {
3830
3814
  scmType: "Ado" /* Ado */,
3831
3815
  organization,
3832
- projectName: z14.string().parse(projectName),
3816
+ projectName: z13.string().parse(projectName),
3833
3817
  repoName,
3834
3818
  prefixPath
3835
3819
  };
@@ -3956,10 +3940,10 @@ function getIssueUrl({
3956
3940
  }
3957
3941
 
3958
3942
  // src/features/analysis/scm/utils/index.ts
3959
- import { z as z16 } from "zod";
3943
+ import { z as z15 } from "zod";
3960
3944
 
3961
3945
  // src/features/analysis/scm/types.ts
3962
- import { z as z15 } from "zod";
3946
+ import { z as z14 } from "zod";
3963
3947
  var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
3964
3948
  ReferenceType2["BRANCH"] = "BRANCH";
3965
3949
  ReferenceType2["COMMIT"] = "COMMIT";
@@ -3991,10 +3975,10 @@ var scmTypeToScmLibScmType = {
3991
3975
  ["Ado" /* Ado */]: "ADO" /* ADO */,
3992
3976
  ["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
3993
3977
  };
3994
- var GetRefererenceResultZ = z15.object({
3995
- date: z15.date().optional(),
3996
- sha: z15.string(),
3997
- type: z15.nativeEnum(ReferenceType)
3978
+ var GetRefererenceResultZ = z14.object({
3979
+ date: z14.date().optional(),
3980
+ sha: z14.string(),
3981
+ type: z14.nativeEnum(ReferenceType)
3998
3982
  });
3999
3983
 
4000
3984
  // src/features/analysis/scm/utils/index.ts
@@ -4108,7 +4092,7 @@ function shouldValidateUrl(repoUrl) {
4108
4092
  return repoUrl && isUrlHasPath(repoUrl);
4109
4093
  }
4110
4094
  function isBrokerUrl(url) {
4111
- return z16.string().uuid().safeParse(new URL(url).host).success;
4095
+ return z15.string().uuid().safeParse(new URL(url).host).success;
4112
4096
  }
4113
4097
  function buildAuthorizedRepoUrl(args) {
4114
4098
  const { url, username, password } = args;
@@ -4144,7 +4128,7 @@ function getCloudScmLibTypeFromUrl(url) {
4144
4128
  return void 0;
4145
4129
  }
4146
4130
  function getScmLibTypeFromScmType(scmType) {
4147
- const parsedScmType = z16.nativeEnum(ScmType).parse(scmType);
4131
+ const parsedScmType = z15.nativeEnum(ScmType).parse(scmType);
4148
4132
  return scmTypeToScmLibScmType[parsedScmType];
4149
4133
  }
4150
4134
  function getScmConfig({
@@ -4211,42 +4195,42 @@ function getScmConfig({
4211
4195
  }
4212
4196
 
4213
4197
  // 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 */)
4198
+ import { z as z16 } from "zod";
4199
+ var ValidPullRequestStatusZ = z16.union([
4200
+ z16.literal(1 /* Active */),
4201
+ z16.literal(2 /* Abandoned */),
4202
+ z16.literal(3 /* Completed */)
4219
4203
  ]);
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)
4204
+ var AdoAuthResultZ = z16.object({
4205
+ access_token: z16.string().min(1),
4206
+ token_type: z16.string().min(1),
4207
+ refresh_token: z16.string().min(1)
4224
4208
  });
4225
4209
  var AdoAuthResultWithOrgsZ = AdoAuthResultZ.extend({
4226
- scmOrgs: z17.array(z17.string())
4210
+ scmOrgs: z16.array(z16.string())
4227
4211
  });
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()
4212
+ var profileZ = z16.object({
4213
+ displayName: z16.string(),
4214
+ publicAlias: z16.string().min(1),
4215
+ emailAddress: z16.string(),
4216
+ coreRevision: z16.number(),
4217
+ timeStamp: z16.string(),
4218
+ id: z16.string(),
4219
+ revision: z16.number()
4236
4220
  });
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()
4221
+ var accountsZ = z16.object({
4222
+ count: z16.number(),
4223
+ value: z16.array(
4224
+ z16.object({
4225
+ accountId: z16.string(),
4226
+ accountUri: z16.string(),
4227
+ accountName: z16.string()
4244
4228
  })
4245
4229
  )
4246
4230
  });
4247
4231
 
4248
4232
  // src/features/analysis/scm/ado/utils.ts
4249
- var debug2 = Debug2("mobbdev:scm:ado");
4233
+ var debug = Debug("mobbdev:scm:ado");
4250
4234
  function _getPublicAdoClient({
4251
4235
  orgName,
4252
4236
  origin: origin2
@@ -4325,7 +4309,7 @@ async function getAdoConnectData({
4325
4309
  oauthToken: adoTokenInfo.accessToken
4326
4310
  });
4327
4311
  return {
4328
- org: z18.string().parse(org),
4312
+ org: z17.string().parse(org),
4329
4313
  origin: DEFUALT_ADO_ORIGIN
4330
4314
  };
4331
4315
  }
@@ -4411,7 +4395,7 @@ async function getAdoClientParams(params) {
4411
4395
  return {
4412
4396
  tokenType: "PAT" /* PAT */,
4413
4397
  accessToken: adoTokenInfo.accessToken,
4414
- patTokenOrg: z18.string().parse(tokenOrg).toLowerCase(),
4398
+ patTokenOrg: z17.string().parse(tokenOrg).toLowerCase(),
4415
4399
  origin: origin2,
4416
4400
  orgName: org.toLowerCase()
4417
4401
  };
@@ -4579,6 +4563,18 @@ async function getAdoSdk(params) {
4579
4563
  );
4580
4564
  return `${getRepositoryRes.webUrl}/commit/${commitId}`;
4581
4565
  },
4566
+ async getAdoBranchCommitsUrl({
4567
+ repoUrl,
4568
+ branch
4569
+ }) {
4570
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
4571
+ const git = await api2.getGitApi();
4572
+ const getRepositoryRes = await git.getRepository(
4573
+ decodeURI(repo),
4574
+ projectName ? decodeURI(projectName) : void 0
4575
+ );
4576
+ return `${getRepositoryRes.webUrl}/commits?itemVersion=${branch}`;
4577
+ },
4582
4578
  getAdoDownloadUrl({
4583
4579
  repoUrl,
4584
4580
  branch
@@ -4587,7 +4583,7 @@ async function getAdoSdk(params) {
4587
4583
  const url = new URL(repoUrl);
4588
4584
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
4589
4585
  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 = [
4586
+ const path9 = [
4591
4587
  prefixPath,
4592
4588
  owner,
4593
4589
  projectName,
@@ -4598,7 +4594,7 @@ async function getAdoSdk(params) {
4598
4594
  "items",
4599
4595
  "items"
4600
4596
  ].filter(Boolean).join("/");
4601
- return new URL(`${path8}?${params2}`, origin2).toString();
4597
+ return new URL(`${path9}?${params2}`, origin2).toString();
4602
4598
  },
4603
4599
  async getAdoBranchList({ repoUrl }) {
4604
4600
  try {
@@ -5080,6 +5076,14 @@ var AdoSCMLib = class extends SCMLib {
5080
5076
  commitId
5081
5077
  });
5082
5078
  }
5079
+ async getBranchCommitsUrl(branchName) {
5080
+ this._validateUrl();
5081
+ const adoSdk = await this.getAdoSdk();
5082
+ return adoSdk.getAdoBranchCommitsUrl({
5083
+ repoUrl: this.url,
5084
+ branch: branchName
5085
+ });
5086
+ }
5083
5087
  async addCommentToSubmitRequest(scmSubmitRequestId, comment) {
5084
5088
  this._validateAccessTokenAndUrl();
5085
5089
  const adoSdk = await this.getAdoSdk();
@@ -5095,34 +5099,34 @@ var AdoSCMLib = class extends SCMLib {
5095
5099
  import querystring2 from "node:querystring";
5096
5100
  import * as bitbucketPkgNode from "bitbucket";
5097
5101
  import bitbucketPkg from "bitbucket";
5098
- import Debug3 from "debug";
5099
- import { z as z20 } from "zod";
5102
+ import Debug2 from "debug";
5103
+ import { z as z19 } from "zod";
5100
5104
 
5101
5105
  // 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()
5106
+ import { z as z18 } from "zod";
5107
+ var BitbucketAuthResultZ = z18.object({
5108
+ access_token: z18.string(),
5109
+ token_type: z18.string(),
5110
+ refresh_token: z18.string()
5107
5111
  });
5108
5112
 
5109
5113
  // src/features/analysis/scm/bitbucket/bitbucket.ts
5110
- var debug3 = Debug3("scm:bitbucket");
5114
+ var debug2 = Debug2("scm:bitbucket");
5111
5115
  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()
5116
+ var TokenExpiredErrorZ = z19.object({
5117
+ status: z19.number(),
5118
+ error: z19.object({
5119
+ type: z19.string(),
5120
+ error: z19.object({
5121
+ message: z19.string()
5118
5122
  })
5119
5123
  })
5120
5124
  });
5121
5125
  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)
5126
+ var BitbucketParseResultZ = z19.object({
5127
+ organization: z19.string(),
5128
+ repoName: z19.string(),
5129
+ hostname: z19.literal(BITBUCKET_HOSTNAME)
5126
5130
  });
5127
5131
  function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
5128
5132
  const parsedGitHubUrl = normalizeUrl(bitbucketUrl);
@@ -5183,7 +5187,7 @@ function getBitbucketSdk(params) {
5183
5187
  if (!res.data.values) {
5184
5188
  return [];
5185
5189
  }
5186
- return res.data.values.filter((branch) => !!branch.name).map((branch) => z20.string().parse(branch.name));
5190
+ return res.data.values.filter((branch) => !!branch.name).map((branch) => z19.string().parse(branch.name));
5187
5191
  },
5188
5192
  async getIsUserCollaborator(params2) {
5189
5193
  const { repoUrl } = params2;
@@ -5298,7 +5302,7 @@ function getBitbucketSdk(params) {
5298
5302
  return GetRefererenceResultZ.parse({
5299
5303
  sha: tagRes.data.target?.hash,
5300
5304
  type: "TAG" /* TAG */,
5301
- date: new Date(z20.string().parse(tagRes.data.target?.date))
5305
+ date: new Date(z19.string().parse(tagRes.data.target?.date))
5302
5306
  });
5303
5307
  },
5304
5308
  async getBranchRef(params2) {
@@ -5306,7 +5310,7 @@ function getBitbucketSdk(params) {
5306
5310
  return GetRefererenceResultZ.parse({
5307
5311
  sha: getBranchRes.target?.hash,
5308
5312
  type: "BRANCH" /* BRANCH */,
5309
- date: new Date(z20.string().parse(getBranchRes.target?.date))
5313
+ date: new Date(z19.string().parse(getBranchRes.target?.date))
5310
5314
  });
5311
5315
  },
5312
5316
  async getCommitRef(params2) {
@@ -5314,13 +5318,13 @@ function getBitbucketSdk(params) {
5314
5318
  return GetRefererenceResultZ.parse({
5315
5319
  sha: getCommitRes.hash,
5316
5320
  type: "COMMIT" /* COMMIT */,
5317
- date: new Date(z20.string().parse(getCommitRes.date))
5321
+ date: new Date(z19.string().parse(getCommitRes.date))
5318
5322
  });
5319
5323
  },
5320
5324
  async getDownloadUrl({ url, sha }) {
5321
5325
  this.getReferenceData({ ref: sha, url });
5322
5326
  const repoRes = await this.getRepo({ repoUrl: url });
5323
- const parsedRepoUrl = z20.string().url().parse(repoRes.links?.html?.href);
5327
+ const parsedRepoUrl = z19.string().url().parse(repoRes.links?.html?.href);
5324
5328
  return `${parsedRepoUrl}/get/${sha}.zip`;
5325
5329
  },
5326
5330
  async getPullRequest(params2) {
@@ -5385,7 +5389,7 @@ async function validateBitbucketParams(params) {
5385
5389
  }
5386
5390
  async function getUsersworkspacesSlugs(bitbucketClient) {
5387
5391
  const res = await bitbucketClient.workspaces.getWorkspaces({});
5388
- return res.data.values?.map((v) => z20.string().parse(v.slug));
5392
+ return res.data.values?.map((v) => z19.string().parse(v.slug));
5389
5393
  }
5390
5394
  async function getllUsersrepositories(bitbucketClient) {
5391
5395
  const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
@@ -5413,10 +5417,10 @@ async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
5413
5417
 
5414
5418
  // src/features/analysis/scm/bitbucket/BitbucketSCMLib.ts
5415
5419
  import { setTimeout as setTimeout3 } from "node:timers/promises";
5416
- import { z as z21 } from "zod";
5420
+ import { z as z20 } from "zod";
5417
5421
  function getUserAndPassword(token) {
5418
5422
  const [username, password] = token.split(":");
5419
- const safePasswordAndUsername = z21.object({ username: z21.string(), password: z21.string() }).parse({ username, password });
5423
+ const safePasswordAndUsername = z20.object({ username: z20.string(), password: z20.string() }).parse({ username, password });
5420
5424
  return {
5421
5425
  username: safePasswordAndUsername.username,
5422
5426
  password: safePasswordAndUsername.password
@@ -5488,7 +5492,7 @@ var BitbucketSCMLib = class extends SCMLib {
5488
5492
  return { username, password, authType };
5489
5493
  }
5490
5494
  case "token": {
5491
- return { authType, token: z21.string().parse(this.accessToken) };
5495
+ return { authType, token: z20.string().parse(this.accessToken) };
5492
5496
  }
5493
5497
  case "public":
5494
5498
  return { authType };
@@ -5502,7 +5506,7 @@ var BitbucketSCMLib = class extends SCMLib {
5502
5506
  ...params,
5503
5507
  repoUrl: this.url
5504
5508
  });
5505
- return String(z21.number().parse(pullRequestRes.id));
5509
+ return String(z20.number().parse(pullRequestRes.id));
5506
5510
  } catch (e) {
5507
5511
  console.warn(
5508
5512
  `error creating pull request for BB. Try number ${i + 1}`,
@@ -5587,7 +5591,7 @@ var BitbucketSCMLib = class extends SCMLib {
5587
5591
  async getUsername() {
5588
5592
  this._validateAccessToken();
5589
5593
  const res = await this.bitbucketSdk.getUser();
5590
- return z21.string().parse(res.username);
5594
+ return z20.string().parse(res.username);
5591
5595
  }
5592
5596
  async getSubmitRequestStatus(_scmSubmitRequestId) {
5593
5597
  this._validateAccessTokenAndUrl();
@@ -5616,7 +5620,7 @@ var BitbucketSCMLib = class extends SCMLib {
5616
5620
  async getRepoDefaultBranch() {
5617
5621
  this._validateUrl();
5618
5622
  const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
5619
- return z21.string().parse(repoRes.mainbranch?.name);
5623
+ return z20.string().parse(repoRes.mainbranch?.name);
5620
5624
  }
5621
5625
  getSubmitRequestUrl(submitRequestId) {
5622
5626
  this._validateUrl();
@@ -5636,6 +5640,13 @@ var BitbucketSCMLib = class extends SCMLib {
5636
5640
  `https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
5637
5641
  );
5638
5642
  }
5643
+ getBranchCommitsUrl(branchName) {
5644
+ this._validateUrl();
5645
+ const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
5646
+ return Promise.resolve(
5647
+ `https://bitbucket.org/${workspace}/${repo_slug}/branch/${branchName}`
5648
+ );
5649
+ }
5639
5650
  async addCommentToSubmitRequest(submitRequestId, comment) {
5640
5651
  this._validateUrl();
5641
5652
  await this.bitbucketSdk.addCommentToPullRequest({
@@ -5651,7 +5662,7 @@ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
5651
5662
  var MAX_BRANCHES_FETCH = 1e3;
5652
5663
 
5653
5664
  // src/features/analysis/scm/github/GithubSCMLib.ts
5654
- import { z as z22 } from "zod";
5665
+ import { z as z21 } from "zod";
5655
5666
 
5656
5667
  // src/features/analysis/scm/github/github.ts
5657
5668
  import { RequestError } from "@octokit/request-error";
@@ -6040,14 +6051,14 @@ function getGithubSdk(params = {}) {
6040
6051
  };
6041
6052
  },
6042
6053
  async getGithubBlameRanges(params2) {
6043
- const { ref, gitHubUrl, path: path8 } = params2;
6054
+ const { ref, gitHubUrl, path: path9 } = params2;
6044
6055
  const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
6045
6056
  const res = await octokit.graphql(
6046
6057
  GET_BLAME_DOCUMENT,
6047
6058
  {
6048
6059
  owner,
6049
6060
  repo,
6050
- path: path8,
6061
+ path: path9,
6051
6062
  ref
6052
6063
  }
6053
6064
  );
@@ -6289,7 +6300,7 @@ var GithubSCMLib = class extends SCMLib {
6289
6300
  owner,
6290
6301
  repo
6291
6302
  });
6292
- return z22.string().parse(prRes.data);
6303
+ return z21.string().parse(prRes.data);
6293
6304
  }
6294
6305
  async getRepoList(_scmOrg) {
6295
6306
  this._validateAccessToken();
@@ -6353,11 +6364,11 @@ var GithubSCMLib = class extends SCMLib {
6353
6364
  markdownComment: comment
6354
6365
  });
6355
6366
  }
6356
- async getRepoBlameRanges(ref, path8) {
6367
+ async getRepoBlameRanges(ref, path9) {
6357
6368
  this._validateUrl();
6358
6369
  return await this.githubSdk.getGithubBlameRanges({
6359
6370
  ref,
6360
- path: path8,
6371
+ path: path9,
6361
6372
  gitHubUrl: this.url
6362
6373
  });
6363
6374
  }
@@ -6402,6 +6413,10 @@ var GithubSCMLib = class extends SCMLib {
6402
6413
  });
6403
6414
  return getCommitRes.data.html_url;
6404
6415
  }
6416
+ async getBranchCommitsUrl(branchName) {
6417
+ this._validateAccessTokenAndUrl();
6418
+ return `${this.url}/commits/${branchName}`;
6419
+ }
6405
6420
  async postGeneralPrComment(params) {
6406
6421
  const { prNumber, body } = params;
6407
6422
  this._validateAccessTokenAndUrl();
@@ -6445,22 +6460,22 @@ import {
6445
6460
  AccessLevel,
6446
6461
  Gitlab
6447
6462
  } from "@gitbeaker/rest";
6448
- import Debug4 from "debug";
6463
+ import Debug3 from "debug";
6449
6464
  import {
6450
6465
  fetch as undiciFetch,
6451
6466
  ProxyAgent as ProxyAgent2
6452
6467
  } from "undici";
6453
6468
 
6454
6469
  // 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()
6470
+ import { z as z22 } from "zod";
6471
+ var GitlabAuthResultZ = z22.object({
6472
+ access_token: z22.string(),
6473
+ token_type: z22.string(),
6474
+ refresh_token: z22.string()
6460
6475
  });
6461
6476
 
6462
6477
  // src/features/analysis/scm/gitlab/gitlab.ts
6463
- var debug4 = Debug4("scm:gitlab");
6478
+ var debug3 = Debug3("scm:gitlab");
6464
6479
  function removeTrailingSlash2(str) {
6465
6480
  return str.trim().replace(/\/+$/, "");
6466
6481
  }
@@ -6755,13 +6770,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
6755
6770
  const { organization, repoName, projectPath } = parsingResult;
6756
6771
  return { owner: organization, repo: repoName, projectPath };
6757
6772
  }
6758
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
6773
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path9 }, options) {
6759
6774
  const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
6760
6775
  const api2 = getGitBeaker({
6761
6776
  url: gitlabUrl,
6762
6777
  gitlabAuthToken: options?.gitlabAuthToken
6763
6778
  });
6764
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
6779
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path9, ref);
6765
6780
  let lineNumber = 1;
6766
6781
  return resp.filter((range) => range.lines).map((range) => {
6767
6782
  const oldLineNumber = lineNumber;
@@ -6937,10 +6952,10 @@ var GitlabSCMLib = class extends SCMLib {
6937
6952
  markdownComment: comment
6938
6953
  });
6939
6954
  }
6940
- async getRepoBlameRanges(ref, path8) {
6955
+ async getRepoBlameRanges(ref, path9) {
6941
6956
  this._validateUrl();
6942
6957
  return await getGitlabBlameRanges(
6943
- { ref, path: path8, gitlabUrl: this.url },
6958
+ { ref, path: path9, gitlabUrl: this.url },
6944
6959
  {
6945
6960
  url: this.url,
6946
6961
  gitlabAuthToken: this.accessToken
@@ -6986,141 +7001,677 @@ var GitlabSCMLib = class extends SCMLib {
6986
7001
  });
6987
7002
  return res.web_url;
6988
7003
  }
7004
+ async getBranchCommitsUrl(branchName) {
7005
+ this._validateAccessTokenAndUrl();
7006
+ return `${this.url}/-/commits/${branchName}`;
7007
+ }
7008
+ };
7009
+
7010
+ // src/features/analysis/scm/scmFactory.ts
7011
+ import { z as z23 } from "zod";
7012
+
7013
+ // src/features/analysis/scm/StubSCMLib.ts
7014
+ var StubSCMLib = class extends SCMLib {
7015
+ constructor(url, accessToken, scmOrg) {
7016
+ super(url, accessToken, scmOrg);
7017
+ }
7018
+ async getUrlWithCredentials() {
7019
+ console.warn("getUrlWithCredentials() returning empty string");
7020
+ return "";
7021
+ }
7022
+ async createSubmitRequest(_params) {
7023
+ console.warn("createSubmitRequest() returning empty string");
7024
+ return "";
7025
+ }
7026
+ get scmLibType() {
7027
+ console.warn("scmLibType returning GITHUB as default");
7028
+ return "GITHUB" /* GITHUB */;
7029
+ }
7030
+ getAuthHeaders() {
7031
+ console.warn("getAuthHeaders() returning empty object");
7032
+ return {};
7033
+ }
7034
+ async getDownloadUrl(_sha) {
7035
+ console.warn("getDownloadUrl() returning empty string");
7036
+ return "";
7037
+ }
7038
+ async getIsRemoteBranch(_branch) {
7039
+ console.warn("getIsRemoteBranch() returning false");
7040
+ return false;
7041
+ }
7042
+ async validateParams() {
7043
+ console.warn("validateParams() no-op");
7044
+ }
7045
+ async getRepoList(_scmOrg) {
7046
+ console.warn("getRepoList() returning empty array");
7047
+ return [];
7048
+ }
7049
+ async getBranchList() {
7050
+ console.warn("getBranchList() returning empty array");
7051
+ return [];
7052
+ }
7053
+ async getUsername() {
7054
+ console.warn("getUsername() returning empty string");
7055
+ return "";
7056
+ }
7057
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
7058
+ console.warn("getSubmitRequestStatus() returning ERROR");
7059
+ return "error";
7060
+ }
7061
+ async getUserHasAccessToRepo() {
7062
+ console.warn("getUserHasAccessToRepo() returning false");
7063
+ return false;
7064
+ }
7065
+ async getRepoBlameRanges(_ref, _path) {
7066
+ console.warn("getRepoBlameRanges() returning empty array");
7067
+ return [];
7068
+ }
7069
+ async getReferenceData(_ref) {
7070
+ console.warn("getReferenceData() returning null/empty defaults");
7071
+ return {
7072
+ type: "BRANCH" /* BRANCH */,
7073
+ sha: "",
7074
+ date: void 0
7075
+ };
7076
+ }
7077
+ async getRepoDefaultBranch() {
7078
+ console.warn("getRepoDefaultBranch() returning empty string");
7079
+ return "";
7080
+ }
7081
+ async getSubmitRequestUrl(_submitRequestIdNumber) {
7082
+ console.warn("getSubmitRequestUrl() returning empty string");
7083
+ return "";
7084
+ }
7085
+ async getSubmitRequestId(_submitRequestUrl) {
7086
+ console.warn("getSubmitRequestId() returning empty string");
7087
+ return "";
7088
+ }
7089
+ async getCommitUrl(_commitId) {
7090
+ console.warn("getCommitUrl() returning empty string");
7091
+ return "";
7092
+ }
7093
+ async getBranchCommitsUrl(_branchName) {
7094
+ console.warn("getBranchCommitsUrl() returning empty string");
7095
+ return "";
7096
+ }
7097
+ async _getUsernameForAuthUrl() {
7098
+ console.warn("_getUsernameForAuthUrl() returning empty string");
7099
+ return "";
7100
+ }
7101
+ async addCommentToSubmitRequest(_submitRequestId, _comment) {
7102
+ console.warn("addCommentToSubmitRequest() no-op");
7103
+ }
7104
+ };
7105
+
7106
+ // src/features/analysis/scm/scmFactory.ts
7107
+ async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
7108
+ const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
7109
+ try {
7110
+ switch (scmType) {
7111
+ case "GITHUB" /* GITHUB */: {
7112
+ const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
7113
+ await scm.validateParams();
7114
+ return scm;
7115
+ }
7116
+ case "GITLAB" /* GITLAB */: {
7117
+ const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
7118
+ await scm.validateParams();
7119
+ return scm;
7120
+ }
7121
+ case "ADO" /* ADO */: {
7122
+ const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
7123
+ await scm.getAdoSdk();
7124
+ await scm.validateParams();
7125
+ return scm;
7126
+ }
7127
+ case "BITBUCKET" /* BITBUCKET */: {
7128
+ const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
7129
+ await scm.validateParams();
7130
+ return scm;
7131
+ }
7132
+ }
7133
+ } catch (e) {
7134
+ if (e instanceof InvalidRepoUrlError && url) {
7135
+ throw new RepoNoTokenAccessError(
7136
+ "no access to repo",
7137
+ scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
7138
+ );
7139
+ }
7140
+ console.error(`error validating scm: ${scmType} `, e);
7141
+ if (propagateExceptions) {
7142
+ throw e;
7143
+ }
7144
+ }
7145
+ return new StubSCMLib(trimmedUrl, void 0, void 0);
7146
+ }
7147
+
7148
+ // src/utils/index.ts
7149
+ var utils_exports = {};
7150
+ __export(utils_exports, {
7151
+ CliError: () => CliError,
7152
+ Spinner: () => Spinner,
7153
+ getDirName: () => getDirName,
7154
+ getTopLevelDirName: () => getTopLevelDirName,
7155
+ keypress: () => keypress,
7156
+ packageJson: () => packageJson,
7157
+ sleep: () => sleep
7158
+ });
7159
+
7160
+ // src/utils/dirname.ts
7161
+ import path from "node:path";
7162
+ import { fileURLToPath } from "node:url";
7163
+ function getDirName() {
7164
+ return path.dirname(fileURLToPath(import.meta.url));
7165
+ }
7166
+ function getTopLevelDirName(fullPath) {
7167
+ return path.parse(fullPath).name;
7168
+ }
7169
+
7170
+ // src/utils/keypress.ts
7171
+ import readline from "node:readline";
7172
+ async function keypress() {
7173
+ const rl = readline.createInterface({
7174
+ input: process.stdin,
7175
+ output: process.stdout
7176
+ });
7177
+ return new Promise((resolve) => {
7178
+ rl.question("", (answer) => {
7179
+ rl.close();
7180
+ process.stderr.moveCursor(0, -1);
7181
+ process.stderr.clearLine(1);
7182
+ resolve(answer);
7183
+ });
7184
+ });
7185
+ }
7186
+
7187
+ // src/utils/spinner.ts
7188
+ import {
7189
+ createSpinner as _createSpinner
7190
+ } from "nanospinner";
7191
+ function printToStdError(opts) {
7192
+ if (opts?.text) console.error(opts.text);
7193
+ }
7194
+ var mockSpinner = {
7195
+ success: (opts) => {
7196
+ printToStdError(opts);
7197
+ return mockSpinner;
7198
+ },
7199
+ error: (opts) => {
7200
+ printToStdError(opts);
7201
+ return mockSpinner;
7202
+ },
7203
+ warn: (opts) => {
7204
+ printToStdError(opts);
7205
+ return mockSpinner;
7206
+ },
7207
+ stop: (opts) => {
7208
+ printToStdError(opts);
7209
+ return mockSpinner;
7210
+ },
7211
+ start: (opts) => {
7212
+ printToStdError(opts);
7213
+ return mockSpinner;
7214
+ },
7215
+ update: (opts) => {
7216
+ printToStdError(opts);
7217
+ return mockSpinner;
7218
+ },
7219
+ reset: () => mockSpinner,
7220
+ clear: () => mockSpinner,
7221
+ spin: () => mockSpinner
7222
+ };
7223
+ function Spinner({ ci = false } = {}) {
7224
+ return {
7225
+ createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
7226
+ };
7227
+ }
7228
+
7229
+ // src/utils/check_node_version.ts
7230
+ import fs2 from "node:fs";
7231
+ import path2 from "node:path";
7232
+ import semver from "semver";
7233
+ function getPackageJson() {
7234
+ let manifestPath = path2.join(getDirName(), "../package.json");
7235
+ if (!fs2.existsSync(manifestPath)) {
7236
+ manifestPath = path2.join(getDirName(), "../../package.json");
7237
+ }
7238
+ return JSON.parse(fs2.readFileSync(manifestPath, "utf8"));
7239
+ }
7240
+ var packageJson = getPackageJson();
7241
+ if (!semver.satisfies(process.version, packageJson.engines.node)) {
7242
+ console.error(
7243
+ `
7244
+ \u26A0\uFE0F ${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
7245
+ );
7246
+ process.exit(1);
7247
+ }
7248
+
7249
+ // src/utils/index.ts
7250
+ var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
7251
+ var CliError = class extends Error {
7252
+ };
7253
+
7254
+ // src/commands/convert_to_sarif.ts
7255
+ import AdmZip from "adm-zip";
7256
+ import multimatch from "multimatch";
7257
+ import tmp from "tmp";
7258
+ async function convertToSarif(options) {
7259
+ switch (options.inputFileFormat) {
7260
+ case "FortifyFPR" /* FortifyFPR */:
7261
+ await convertFprToSarif(
7262
+ options.inputFilePath,
7263
+ options.outputFilePath,
7264
+ options.codePathPatterns ?? ["**", "*"]
7265
+ );
7266
+ break;
7267
+ }
7268
+ }
7269
+ async function convertFprToSarif(inputFilePath, outputFilePath, codePathPatterns) {
7270
+ const zipIn = new AdmZip(inputFilePath);
7271
+ if (!zipIn.getEntry("audit.fvdl")) {
7272
+ throw new CliError(
7273
+ "\nError: the input file should be in a valid Fortify FPR format."
7274
+ );
7275
+ }
7276
+ const tmpObj = tmp.dirSync({
7277
+ unsafeCleanup: true
7278
+ });
7279
+ try {
7280
+ zipIn.extractEntryTo("audit.fvdl", tmpObj.name);
7281
+ const auditFvdlSaxParser = initSaxParser(
7282
+ path3.join(tmpObj.name, "audit.fvdl")
7283
+ );
7284
+ const vulnerabilityParser = new VulnerabilityParser(
7285
+ auditFvdlSaxParser.parser
7286
+ );
7287
+ const unifiedNodePoolParser = new UnifiedNodePoolParser(
7288
+ auditFvdlSaxParser.parser
7289
+ );
7290
+ const reportMetadataParser = new ReportMetadataParser(
7291
+ auditFvdlSaxParser.parser
7292
+ );
7293
+ let auditMetadataParser = null;
7294
+ await auditFvdlSaxParser.parse();
7295
+ if (zipIn.getEntry("audit.xml")) {
7296
+ zipIn.extractEntryTo("audit.xml", tmpObj.name);
7297
+ const auditXmlSaxParser = initSaxParser(
7298
+ path3.join(tmpObj.name, "audit.xml")
7299
+ );
7300
+ auditMetadataParser = new AuditMetadataParser(auditXmlSaxParser.parser);
7301
+ await auditXmlSaxParser.parse();
7302
+ }
7303
+ fs3.writeFileSync(
7304
+ outputFilePath,
7305
+ `{
7306
+ "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
7307
+ "version": "2.1.0",
7308
+ "runs": [
7309
+ {
7310
+ "tool": {
7311
+ "driver": {
7312
+ "name": "Fortify Mobb Converter"
7313
+ }
7314
+ },
7315
+ "results": [
7316
+ `
7317
+ );
7318
+ vulnerabilityParser.getVulnerabilities().map(
7319
+ (vulnerability) => fortifyVulnerabilityToSarifResult(
7320
+ vulnerability,
7321
+ auditMetadataParser,
7322
+ reportMetadataParser,
7323
+ unifiedNodePoolParser
7324
+ )
7325
+ ).filter((sarifResult) => filterSarifResult(sarifResult, codePathPatterns)).forEach((sarifResult, index) => {
7326
+ fs3.appendFileSync(outputFilePath, JSON.stringify(sarifResult, null, 2));
7327
+ if (index !== vulnerabilityParser.getVulnerabilities().length - 1) {
7328
+ fs3.appendFileSync(outputFilePath, ",\n");
7329
+ }
7330
+ });
7331
+ fs3.appendFileSync(outputFilePath, "\n]}]}");
7332
+ } finally {
7333
+ tmpObj.removeCallback();
7334
+ }
7335
+ }
7336
+ function filterSarifResult(sarifResult, codePathPatterns) {
7337
+ const paths = sarifResult.locations.map(
7338
+ (l) => l.physicalLocation.artifactLocation.uri
7339
+ );
7340
+ const matchPaths = multimatch(paths, codePathPatterns, {
7341
+ dot: true
7342
+ });
7343
+ return matchPaths.length > 0;
7344
+ }
7345
+ function fortifyVulnerabilityToSarifResult(vulnerability, auditMetadataParser, reportMetadataParser, unifiedNodePoolParser) {
7346
+ const suppressed = auditMetadataParser?.getAuditMetadata()[vulnerability.instanceID] || "false";
7347
+ const ruleMeta = reportMetadataParser.getReportMetadata().rules[vulnerability.classID] ?? {};
7348
+ return {
7349
+ ruleId: vulnerability.type + (vulnerability.subtype ? `: ${vulnerability.subtype}` : ""),
7350
+ properties: {
7351
+ package: ruleMeta["package"] ?? "",
7352
+ probability: vulnerability.metaInfo["Probability"] ?? ruleMeta["Probability"] ?? "",
7353
+ impact: vulnerability.metaInfo["Impact"] ?? ruleMeta["Impact"] ?? "",
7354
+ accuracy: vulnerability.metaInfo["Accuracy"] ?? ruleMeta["Accuracy"] ?? "",
7355
+ confidence: vulnerability.confidence,
7356
+ instanceID: vulnerability.instanceID,
7357
+ instanceSeverity: vulnerability.instanceSeverity,
7358
+ suppressed
7359
+ },
7360
+ locations: fortifyNodesToSarifLocations(
7361
+ vulnerability.nodes,
7362
+ unifiedNodePoolParser
7363
+ ),
7364
+ message: {
7365
+ text: "no message"
7366
+ }
7367
+ };
7368
+ }
7369
+ function fortifyNodesToSarifLocations(nodes, unifiedNodePoolParser) {
7370
+ return nodes.map((node) => {
7371
+ let sourceLocation;
7372
+ if ("id" in node) {
7373
+ const poolNode = unifiedNodePoolParser.getNodesPull()[node.id];
7374
+ if (poolNode) {
7375
+ sourceLocation = poolNode;
7376
+ } else {
7377
+ throw new CliError(
7378
+ "\nError: the input file should be in a valid Fortify FPR format (broken unified node pool)."
7379
+ );
7380
+ }
7381
+ } else {
7382
+ sourceLocation = node;
7383
+ }
7384
+ return {
7385
+ physicalLocation: {
7386
+ artifactLocation: {
7387
+ uri: sourceLocation.path
7388
+ },
7389
+ region: {
7390
+ startLine: parseInt(sourceLocation.line || "0", 10),
7391
+ endLine: sourceLocation.lineEnd ? parseInt(sourceLocation.lineEnd, 10) : void 0,
7392
+ startColumn: parseInt(sourceLocation.colStart || "0", 10),
7393
+ endColumn: sourceLocation.colEnd ? parseInt(sourceLocation.colEnd, 10) : void 0
7394
+ }
7395
+ }
7396
+ };
7397
+ });
7398
+ }
7399
+
7400
+ // src/args/options.ts
7401
+ import chalk2 from "chalk";
7402
+
7403
+ // src/constants.ts
7404
+ import path4 from "node:path";
7405
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
7406
+ import chalk from "chalk";
7407
+ import Debug4 from "debug";
7408
+ import * as dotenv from "dotenv";
7409
+ import { z as z24 } from "zod";
7410
+ var debug4 = Debug4("mobbdev:constants");
7411
+ var __dirname = path4.dirname(fileURLToPath2(import.meta.url));
7412
+ dotenv.config({ path: path4.join(__dirname, "../.env") });
7413
+ var scmFriendlyText = {
7414
+ ["Ado" /* Ado */]: "Azure DevOps",
7415
+ ["Bitbucket" /* Bitbucket */]: "Bitbucket",
7416
+ ["GitHub" /* GitHub */]: "GitGub",
7417
+ ["GitLab" /* GitLab */]: "GitLab"
7418
+ };
7419
+ var SCANNERS = {
7420
+ Checkmarx: "checkmarx",
7421
+ Codeql: "codeql",
7422
+ Fortify: "fortify",
7423
+ Snyk: "snyk",
7424
+ Sonarqube: "sonarqube",
7425
+ Semgrep: "semgrep",
7426
+ Datadog: "datadog"
7427
+ };
7428
+ var scannerToVulnerability_Report_Vendor_Enum = {
7429
+ [SCANNERS.Checkmarx]: "checkmarx" /* Checkmarx */,
7430
+ [SCANNERS.Snyk]: "snyk" /* Snyk */,
7431
+ [SCANNERS.Sonarqube]: "sonarqube" /* Sonarqube */,
7432
+ [SCANNERS.Codeql]: "codeql" /* Codeql */,
7433
+ [SCANNERS.Fortify]: "fortify" /* Fortify */,
7434
+ [SCANNERS.Semgrep]: "semgrep" /* Semgrep */,
7435
+ [SCANNERS.Datadog]: "datadog" /* Datadog */
7436
+ };
7437
+ var SupportedScannersZ = z24.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
7438
+ var envVariablesSchema = z24.object({
7439
+ WEB_APP_URL: z24.string(),
7440
+ API_URL: z24.string(),
7441
+ HASURA_ACCESS_KEY: z24.string(),
7442
+ LOCAL_GRAPHQL_ENDPOINT: z24.string(),
7443
+ HTTP_PROXY: z24.string().optional().default(""),
7444
+ HTTPS_PROXY: z24.string().optional().default("")
7445
+ }).required();
7446
+ var envVariables = envVariablesSchema.parse(process.env);
7447
+ debug4("config %o", envVariables);
7448
+ var mobbAscii = `
7449
+ ..
7450
+ ..........
7451
+ .................
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
+ var PROJECT_DEFAULT_NAME = "My first project";
7477
+ var WEB_APP_URL = envVariables.WEB_APP_URL;
7478
+ var API_URL = envVariables.API_URL;
7479
+ var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
7480
+ var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
7481
+ var HTTPS_PROXY = envVariables.HTTPS_PROXY;
7482
+ var HTTP_PROXY = envVariables.HTTP_PROXY;
7483
+ var errorMessages = {
7484
+ missingCxProjectName: `project name ${chalk.bold(
7485
+ "(--cx-project-name)"
7486
+ )} is needed if you're using checkmarx`,
7487
+ missingUrl: `url ${chalk.bold(
7488
+ "(--url)"
7489
+ )} is needed if you're adding an SCM token`,
7490
+ invalidScmType: `SCM type ${chalk.bold(
7491
+ "(--scm-type)"
7492
+ )} is invalid, please use one of: ${Object.values(ScmType).join(", ")}`,
7493
+ missingToken: `SCM token ${chalk.bold(
7494
+ "(--token)"
7495
+ )} is needed if you're adding an SCM token`
7496
+ };
7497
+ var progressMassages = {
7498
+ processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
7499
+ processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
7500
+ processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
7501
+ };
7502
+ var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
7503
+
7504
+ // src/args/options.ts
7505
+ var repoOption = {
7506
+ alias: "r",
7507
+ demandOption: true,
7508
+ type: "string",
7509
+ describe: chalk2.bold("Github / GitLab / Azure DevOps repository URL")
7510
+ };
7511
+ var projectNameOption = {
7512
+ type: "string",
7513
+ describe: chalk2.bold("Checkmarx project name (when scanning with Checkmarx)")
7514
+ };
7515
+ var yesOption = {
7516
+ alias: "yes",
7517
+ type: "boolean",
7518
+ describe: chalk2.bold("Skip prompts and use default values")
7519
+ };
7520
+ var refOption = {
7521
+ describe: chalk2.bold("Reference of the repository (branch, tag, commit)"),
7522
+ type: "string",
7523
+ demandOption: false
7524
+ };
7525
+ var organizationIdOptions = {
7526
+ describe: chalk2.bold("Organization id"),
7527
+ alias: "organization-id",
7528
+ type: "string",
7529
+ demandOption: false
7530
+ };
7531
+ var scannerOptions = {
7532
+ alias: "s",
7533
+ choices: Object.values(SCANNERS),
7534
+ describe: chalk2.bold("Select the scanner to use")
7535
+ };
7536
+ var mobbProjectNameOption = {
7537
+ type: "string",
7538
+ describe: chalk2.bold("Mobb project name"),
7539
+ default: PROJECT_DEFAULT_NAME
7540
+ };
7541
+ var ciOption = {
7542
+ describe: chalk2.bold(
7543
+ "Run in CI mode, prompts and browser will not be opened"
7544
+ ),
7545
+ type: "boolean",
7546
+ default: false
7547
+ };
7548
+ var apiKeyOption = {
7549
+ type: "string",
7550
+ describe: chalk2.bold("Mobb authentication api-key")
7551
+ };
7552
+ var commitHashOption = {
7553
+ alias: "ch",
7554
+ describe: chalk2.bold("Hash of the commit"),
7555
+ type: "string"
7556
+ };
7557
+ var autoPrOption = {
7558
+ describe: chalk2.bold("Enable automatic pull requests for new fixes"),
7559
+ type: "boolean",
7560
+ default: false
7561
+ };
7562
+ var commitDirectlyOption = {
7563
+ describe: chalk2.bold(
7564
+ "Commit directly to the scanned branch instead of creating a pull request"
7565
+ ),
7566
+ type: "boolean",
7567
+ default: false
7568
+ };
7569
+ var scmTypeOption = {
7570
+ demandOption: true,
7571
+ describe: chalk2.bold("SCM type"),
7572
+ choices: Object.values(ScmType)
7573
+ };
7574
+ var urlOption = {
7575
+ describe: chalk2.bold(
7576
+ `URL of the repository (used in ${Object.values(ScmType).join(", ")})`
7577
+ ),
7578
+ type: "string",
7579
+ demandOption: true
7580
+ };
7581
+ var scmOrgOption = {
7582
+ describe: chalk2.bold("Organization name in SCM (used in Azure DevOps)"),
7583
+ type: "string"
7584
+ };
7585
+ var scmRefreshTokenOption = {
7586
+ describe: chalk2.bold("SCM refresh token (used in GitLab)"),
7587
+ type: "string"
7588
+ };
7589
+ var scmTokenOption = {
7590
+ describe: chalk2.bold("SCM API token"),
7591
+ type: "string",
7592
+ demandOption: true
7593
+ };
7594
+ var convertToSarifInputFilePathOption = {
7595
+ demandOption: true,
7596
+ describe: chalk2.bold("Original SAST report file path"),
7597
+ type: "string"
7598
+ };
7599
+ var convertToSarifOutputFilePathOption = {
7600
+ demandOption: true,
7601
+ describe: chalk2.bold("Output SARIF report file path"),
7602
+ type: "string"
7603
+ };
7604
+ var convertToSarifInputFileFormatOption = {
7605
+ demandOption: true,
7606
+ choices: Object.values(ConvertToSarifInputFileFormat),
7607
+ describe: chalk2.bold("SAST report file type")
6989
7608
  };
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
- }
7609
+ var convertToSarifCodePathPatternsOption = {
7610
+ demandOption: false,
7611
+ describe: chalk2.bold(
7612
+ "Glob-like patterns. Any code node with this pattern makes the issue be included."
7613
+ ),
7614
+ type: "string",
7615
+ array: true
7081
7616
  };
7082
7617
 
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
- }
7618
+ // src/args/commands/convert_to_sarif.ts
7619
+ function convertToSarifBuilder(args) {
7620
+ return args.option("input-file-path", convertToSarifInputFilePathOption).option("input-file-format", convertToSarifInputFileFormatOption).option("output-file-path", convertToSarifOutputFilePathOption).option("code-path-patterns", convertToSarifCodePathPatternsOption).example(
7621
+ "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",
7622
+ "convert an existing SAST report to SARIF format"
7623
+ ).help().demandOption(["input-file-path", "input-file-format", "output-file-path"]);
7624
+ }
7625
+ async function validateConvertToSarifOptions(args) {
7626
+ if (!fs4.existsSync(args.inputFilePath)) {
7627
+ throw new CliError(
7628
+ "\nError: --input-file-path flag should point to an existing file"
7629
+ );
7121
7630
  }
7122
- return new StubSCMLib(trimmedUrl, void 0, void 0);
7123
7631
  }
7632
+ async function convertToSarifHandler(args) {
7633
+ await validateConvertToSarifOptions(args);
7634
+ await convertToSarif(args);
7635
+ }
7636
+
7637
+ // src/types.ts
7638
+ var mobbCliCommand = {
7639
+ addScmToken: "add-scm-token",
7640
+ scan: "scan",
7641
+ analyze: "analyze",
7642
+ review: "review",
7643
+ convertToSarif: "convert-to-sarif"
7644
+ };
7645
+
7646
+ // src/args/yargs.ts
7647
+ import chalk10 from "chalk";
7648
+ import yargs from "yargs/yargs";
7649
+
7650
+ // src/args/commands/analyze.ts
7651
+ import fs7 from "node:fs";
7652
+
7653
+ // src/commands/index.ts
7654
+ import crypto from "node:crypto";
7655
+ import os from "node:os";
7656
+
7657
+ // src/features/analysis/index.ts
7658
+ import fs6 from "node:fs";
7659
+ import fsPromises from "node:fs/promises";
7660
+ import path7 from "node:path";
7661
+ import { env as env2 } from "node:process";
7662
+ import { pipeline } from "node:stream/promises";
7663
+ import chalk5 from "chalk";
7664
+ import Configstore from "configstore";
7665
+ import Debug18 from "debug";
7666
+ import extract from "extract-zip";
7667
+ import { createSpinner as createSpinner4 } from "nanospinner";
7668
+ import fetch4 from "node-fetch";
7669
+ import open2 from "open";
7670
+ import tmp2 from "tmp";
7671
+ import { z as z29 } from "zod";
7672
+
7673
+ // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
7674
+ import Debug8 from "debug";
7124
7675
 
7125
7676
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
7126
7677
  import Debug7 from "debug";
@@ -7390,7 +7941,7 @@ async function postIssueComment(params) {
7390
7941
  fpDescription
7391
7942
  } = params;
7392
7943
  const {
7393
- path: path8,
7944
+ path: path9,
7394
7945
  startLine,
7395
7946
  vulnerabilityReportIssue: {
7396
7947
  vulnerabilityReportIssueTags,
@@ -7405,7 +7956,7 @@ async function postIssueComment(params) {
7405
7956
  Refresh the page in order to see the changes.`,
7406
7957
  pull_number: pullRequest,
7407
7958
  commit_id: commitSha,
7408
- path: path8,
7959
+ path: path9,
7409
7960
  line: startLine
7410
7961
  });
7411
7962
  const commentId = commentRes.data.id;
@@ -7439,7 +7990,7 @@ async function postFixComment(params) {
7439
7990
  scanner
7440
7991
  } = params;
7441
7992
  const {
7442
- path: path8,
7993
+ path: path9,
7443
7994
  startLine,
7444
7995
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
7445
7996
  vulnerabilityReportIssueId
@@ -7457,7 +8008,7 @@ async function postFixComment(params) {
7457
8008
  Refresh the page in order to see the changes.`,
7458
8009
  pull_number: pullRequest,
7459
8010
  commit_id: commitSha,
7460
- path: path8,
8011
+ path: path9,
7461
8012
  line: startLine
7462
8013
  });
7463
8014
  const commentId = commentRes.data.id;
@@ -8275,9 +8826,9 @@ var GQLClient = class {
8275
8826
  };
8276
8827
 
8277
8828
  // src/features/analysis/pack.ts
8278
- import fs2 from "node:fs";
8279
- import path4 from "node:path";
8280
- import AdmZip from "adm-zip";
8829
+ import fs5 from "node:fs";
8830
+ import path5 from "node:path";
8831
+ import AdmZip2 from "adm-zip";
8281
8832
  import Debug13 from "debug";
8282
8833
  import { globby } from "globby";
8283
8834
  import { isBinary } from "istextorbinary";
@@ -8339,23 +8890,23 @@ async function pack(srcDirPath, vulnFiles) {
8339
8890
  dot: true
8340
8891
  });
8341
8892
  debug13("files found %d", filepaths.length);
8342
- const zip = new AdmZip();
8893
+ const zip = new AdmZip2();
8343
8894
  debug13("compressing files");
8344
8895
  for (const filepath of filepaths) {
8345
- const absFilepath = path4.join(srcDirPath, filepath.toString());
8896
+ const absFilepath = path5.join(srcDirPath, filepath.toString());
8346
8897
  vulnFiles = vulnFiles.concat(_get_manifest_files_suffixes());
8347
8898
  if (!endsWithAny(
8348
- absFilepath.toString().replaceAll(path4.win32.sep, path4.posix.sep),
8899
+ absFilepath.toString().replaceAll(path5.win32.sep, path5.posix.sep),
8349
8900
  vulnFiles
8350
8901
  )) {
8351
8902
  debug13("ignoring %s because it is not a vulnerability file", filepath);
8352
8903
  continue;
8353
8904
  }
8354
- if (fs2.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
8905
+ if (fs5.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
8355
8906
  debug13("ignoring %s because the size is > 5MB", filepath);
8356
8907
  continue;
8357
8908
  }
8358
- const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs2.readFileSync(absFilepath);
8909
+ const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs5.readFileSync(absFilepath);
8359
8910
  if (isBinary(null, data)) {
8360
8911
  debug13("ignoring %s because is seems to be a binary file", filepath);
8361
8912
  continue;
@@ -8367,8 +8918,8 @@ async function pack(srcDirPath, vulnFiles) {
8367
8918
  }
8368
8919
  async function repackFpr(fprPath) {
8369
8920
  debug13("repack fpr file %s", fprPath);
8370
- const zipIn = new AdmZip(fprPath);
8371
- const zipOut = new AdmZip();
8921
+ const zipIn = new AdmZip2(fprPath);
8922
+ const zipOut = new AdmZip2();
8372
8923
  const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
8373
8924
  const filesMapping = FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA.parse(
8374
8925
  await parseStringPromise(mappingXML)
@@ -8507,12 +9058,12 @@ function createChildProcess({ childProcess, name }, options) {
8507
9058
  }
8508
9059
 
8509
9060
  // src/features/analysis/scanners/checkmarx.ts
8510
- import chalk2 from "chalk";
9061
+ import chalk3 from "chalk";
8511
9062
  import Debug15 from "debug";
8512
9063
  import { existsSync } from "fs";
8513
9064
  import { createSpinner as createSpinner2 } from "nanospinner";
8514
9065
  import { type } from "os";
8515
- import path5 from "path";
9066
+ import path6 from "path";
8516
9067
  var debug14 = Debug15("mobbdev:checkmarx");
8517
9068
  var require2 = createRequire(import.meta.url);
8518
9069
  var getCheckmarxPath = () => {
@@ -8572,9 +9123,9 @@ async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectN
8572
9123
  await startCheckmarxConfigationPrompt();
8573
9124
  await validateCheckamxCredentials();
8574
9125
  }
8575
- const extension = path5.extname(reportPath);
8576
- const filePath = path5.dirname(reportPath);
8577
- const fileName = path5.basename(reportPath, extension);
9126
+ const extension = path6.extname(reportPath);
9127
+ const filePath = path6.dirname(reportPath);
9128
+ const fileName = path6.basename(reportPath, extension);
8578
9129
  const checkmarxCommandArgs = getCheckmarxCommandArgs({
8579
9130
  repoPath: repositoryRoot,
8580
9131
  branch,
@@ -8600,7 +9151,7 @@ async function throwCheckmarxConfigError() {
8600
9151
  await createSpinner2("\u{1F513} Checkmarx is not configued correctly").start().error();
8601
9152
  throw new CliError(
8602
9153
  `Checkmarx is not configued correctly
8603
- you can configure it by using the ${chalk2.bold(
9154
+ you can configure it by using the ${chalk3.bold(
8604
9155
  "cx configure"
8605
9156
  )} command`
8606
9157
  );
@@ -8608,8 +9159,8 @@ async function throwCheckmarxConfigError() {
8608
9159
  async function validateCheckamxCredentials() {
8609
9160
  console.log(`
8610
9161
  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
9162
+ ${chalk3.bold("AST Base URI:")} https://ast.checkmarx.net
9163
+ ${chalk3.bold("AST Base Auth URI (IAM):")} https://iam.checkmarx.net
8613
9164
  `);
8614
9165
  await forkCheckmarx(CONFIGURE_COMMAND, { display: true });
8615
9166
  const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
@@ -8628,7 +9179,7 @@ async function validateCheckamxCredentials() {
8628
9179
 
8629
9180
  // src/features/analysis/scanners/snyk.ts
8630
9181
  import { createRequire as createRequire2 } from "node:module";
8631
- import chalk3 from "chalk";
9182
+ import chalk4 from "chalk";
8632
9183
  import Debug16 from "debug";
8633
9184
  import { createSpinner as createSpinner3 } from "nanospinner";
8634
9185
  import open from "open";
@@ -8675,7 +9226,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8675
9226
  await open(SNYK_ARTICLE_URL);
8676
9227
  }
8677
9228
  console.log(
8678
- chalk3.bgBlue(
9229
+ chalk4.bgBlue(
8679
9230
  "\nPlease enable Snyk Code in your Snyk account and try again."
8680
9231
  )
8681
9232
  );
@@ -8757,7 +9308,7 @@ async function downloadRepo({
8757
9308
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
8758
9309
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
8759
9310
  debug17("download repo %s %s %s", repoUrl, dirname);
8760
- const zipFilePath = path6.join(dirname, "repo.zip");
9311
+ const zipFilePath = path7.join(dirname, "repo.zip");
8761
9312
  debug17("download URL: %s auth headers: %o", downloadUrl, authHeaders);
8762
9313
  const response = await fetch4(downloadUrl, {
8763
9314
  method: "GET",
@@ -8768,21 +9319,21 @@ async function downloadRepo({
8768
9319
  if (!response.ok) {
8769
9320
  debug17("SCM zipball request failed %s %s", response.body, response.status);
8770
9321
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
8771
- throw new Error(`Can't access ${chalk4.bold(repoUrl)}`);
9322
+ throw new Error(`Can't access ${chalk5.bold(repoUrl)}`);
8772
9323
  }
8773
- const fileWriterStream = fs3.createWriteStream(zipFilePath);
9324
+ const fileWriterStream = fs6.createWriteStream(zipFilePath);
8774
9325
  if (!response.body) {
8775
9326
  throw new Error("Response body is empty");
8776
9327
  }
8777
9328
  await pipeline(response.body, fileWriterStream);
8778
9329
  await extract(zipFilePath, { dir: dirname });
8779
- const repoRoot = fs3.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
9330
+ const repoRoot = fs6.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
8780
9331
  if (!repoRoot) {
8781
9332
  throw new Error("Repo root not found");
8782
9333
  }
8783
9334
  debug17("repo root %s", repoRoot);
8784
9335
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
8785
- return path6.join(dirname, repoRoot);
9336
+ return path7.join(dirname, repoRoot);
8786
9337
  }
8787
9338
  var getReportUrl = ({
8788
9339
  organizationId,
@@ -8793,7 +9344,7 @@ var debug17 = Debug18("mobbdev:index");
8793
9344
  var config2 = new Configstore(packageJson.name, { apiToken: "" });
8794
9345
  debug17("config %o", config2);
8795
9346
  async function runAnalysis(params, options) {
8796
- const tmpObj = tmp.dirSync({
9347
+ const tmpObj = tmp2.dirSync({
8797
9348
  unsafeCleanup: true
8798
9349
  });
8799
9350
  try {
@@ -8892,7 +9443,7 @@ async function getReport(params, { skipPrompts }) {
8892
9443
  authHeaders: scm.getAuthHeaders(),
8893
9444
  downloadUrl
8894
9445
  });
8895
- const reportPath = path6.join(dirname, "report.json");
9446
+ const reportPath = path7.join(dirname, "report.json");
8896
9447
  switch (scanner) {
8897
9448
  case "snyk":
8898
9449
  await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
@@ -9099,11 +9650,11 @@ async function _scan(params, { skipPrompts = false } = {}) {
9099
9650
  fixReportId: reportUploadInfo.fixReportId
9100
9651
  });
9101
9652
  !ci && console.log("You can access the analysis at: \n");
9102
- console.log(chalk4.bold(reportUrl));
9653
+ console.log(chalk5.bold(reportUrl));
9103
9654
  !skipPrompts && await mobbAnalysisPrompt();
9104
9655
  !ci && open2(reportUrl);
9105
9656
  !ci && console.log(
9106
- chalk4.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
9657
+ chalk5.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
9107
9658
  );
9108
9659
  }
9109
9660
  async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
@@ -9180,7 +9731,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
9180
9731
  const zippingSpinner = createSpinner5("\u{1F4E6} Zipping repo").start();
9181
9732
  let zipBuffer;
9182
9733
  let gitInfo = { success: false };
9183
- if (srcFileStatus.isFile() && path6.extname(srcPath).toLowerCase() === ".fpr") {
9734
+ if (srcFileStatus.isFile() && path7.extname(srcPath).toLowerCase() === ".fpr") {
9184
9735
  zipBuffer = await repackFpr(srcPath);
9185
9736
  } else {
9186
9737
  gitInfo = await getGitInfo(srcPath);
@@ -9333,7 +9884,7 @@ async function waitForAnaysisAndReviewPr({
9333
9884
  }
9334
9885
 
9335
9886
  // src/commands/index.ts
9336
- import chalk5 from "chalk";
9887
+ import chalk6 from "chalk";
9337
9888
  import chalkAnimation from "chalk-animation";
9338
9889
  import Configstore2 from "configstore";
9339
9890
  import Debug19 from "debug";
@@ -9466,7 +10017,7 @@ async function showWelcomeMessage(skipPrompts = false) {
9466
10017
  var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
9467
10018
  var LOGIN_CHECK_DELAY = 5 * 1e3;
9468
10019
  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(
10020
+ 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
10021
  "press any key to continue"
9471
10022
  )};`;
9472
10023
  async function handleMobbLogin({
@@ -9560,101 +10111,9 @@ async function handleMobbLogin({
9560
10111
  // src/args/commands/analyze.ts
9561
10112
  import chalk8 from "chalk";
9562
10113
 
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
10114
  // src/args/validation.ts
9656
10115
  import chalk7 from "chalk";
9657
- import path7 from "path";
10116
+ import path8 from "path";
9658
10117
  import { z as z30 } from "zod";
9659
10118
  function throwRepoUrlErrorMessage({
9660
10119
  error,
@@ -9698,7 +10157,7 @@ function validateRepoUrl(args) {
9698
10157
  }
9699
10158
  var supportExtensions = [".json", ".xml", ".fpr", ".sarif"];
9700
10159
  function validateReportFileFormat(reportFile) {
9701
- if (!supportExtensions.includes(path7.extname(reportFile))) {
10160
+ if (!supportExtensions.includes(path8.extname(reportFile))) {
9702
10161
  throw new CliError(
9703
10162
  `
9704
10163
  ${chalk7.bold(
@@ -9741,7 +10200,7 @@ function analyzeBuilder(yargs2) {
9741
10200
  ).help();
9742
10201
  }
9743
10202
  function validateAnalyzeOptions(argv) {
9744
- if (!fs4.existsSync(argv.f)) {
10203
+ if (!fs7.existsSync(argv.f)) {
9745
10204
  throw new CliError(`
9746
10205
  Can't access ${chalk8.bold(argv.f)}`);
9747
10206
  }
@@ -9773,7 +10232,7 @@ async function analyzeHandler(args) {
9773
10232
  }
9774
10233
 
9775
10234
  // src/args/commands/review.ts
9776
- import fs5 from "node:fs";
10235
+ import fs8 from "node:fs";
9777
10236
  import chalk9 from "chalk";
9778
10237
  function reviewBuilder(yargs2) {
9779
10238
  return yargs2.option("f", {
@@ -9810,7 +10269,7 @@ function reviewBuilder(yargs2) {
9810
10269
  ).help();
9811
10270
  }
9812
10271
  function validateReviewOptions(argv) {
9813
- if (!fs5.existsSync(argv.f)) {
10272
+ if (!fs8.existsSync(argv.f)) {
9814
10273
  throw new CliError(`
9815
10274
  Can't access ${chalk9.bold(argv.f)}`);
9816
10275
  }
@@ -9926,6 +10385,11 @@ var parseArgs = async (args) => {
9926
10385
  ),
9927
10386
  addScmTokenBuilder,
9928
10387
  addScmTokenHandler
10388
+ ).command(
10389
+ mobbCliCommand.convertToSarif,
10390
+ chalk10.bold("Convert an existing SAST report to SARIF format."),
10391
+ convertToSarifBuilder,
10392
+ convertToSarifHandler
9929
10393
  ).example(
9930
10394
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
9931
10395
  "Scan an existing repository"