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