mobbdev 1.0.1 → 1.0.2
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 +170 -132
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -21,12 +21,16 @@ var mobbCliCommand = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// src/args/yargs.ts
|
|
24
|
-
import
|
|
24
|
+
import chalk10 from "chalk";
|
|
25
25
|
import yargs from "yargs/yargs";
|
|
26
26
|
|
|
27
27
|
// src/args/commands/analyze.ts
|
|
28
28
|
import fs5 from "node:fs";
|
|
29
29
|
|
|
30
|
+
// src/commands/index.ts
|
|
31
|
+
import crypto from "node:crypto";
|
|
32
|
+
import os from "node:os";
|
|
33
|
+
|
|
30
34
|
// src/constants.ts
|
|
31
35
|
import path from "node:path";
|
|
32
36
|
import { fileURLToPath } from "node:url";
|
|
@@ -159,6 +163,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
159
163
|
IssueType_Enum2["RegexInjection"] = "REGEX_INJECTION";
|
|
160
164
|
IssueType_Enum2["SqlInjection"] = "SQL_Injection";
|
|
161
165
|
IssueType_Enum2["Ssrf"] = "SSRF";
|
|
166
|
+
IssueType_Enum2["StringFormatMisuse"] = "STRING_FORMAT_MISUSE";
|
|
162
167
|
IssueType_Enum2["SystemInformationLeak"] = "SYSTEM_INFORMATION_LEAK";
|
|
163
168
|
IssueType_Enum2["SystemInformationLeakExternal"] = "SYSTEM_INFORMATION_LEAK_EXTERNAL";
|
|
164
169
|
IssueType_Enum2["TrustBoundaryViolation"] = "TRUST_BOUNDARY_VIOLATION";
|
|
@@ -414,6 +419,9 @@ var UpdateScmTokenDocument = `
|
|
|
414
419
|
status
|
|
415
420
|
error
|
|
416
421
|
}
|
|
422
|
+
... on RepoUnreachableError {
|
|
423
|
+
status
|
|
424
|
+
}
|
|
417
425
|
}
|
|
418
426
|
}
|
|
419
427
|
`;
|
|
@@ -731,7 +739,8 @@ var issueTypeMap = {
|
|
|
731
739
|
["MISSING_CSP_HEADER" /* MissingCspHeader */]: "Missing CSP Header",
|
|
732
740
|
["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: "Hardcoded Domain in HTML",
|
|
733
741
|
["HEAP_INSPECTION" /* HeapInspection */]: "Heap Inspection",
|
|
734
|
-
["CLIENT_DOM_STORED_CODE_INJECTION" /* ClientDomStoredCodeInjection */]: "Client Code Injection"
|
|
742
|
+
["CLIENT_DOM_STORED_CODE_INJECTION" /* ClientDomStoredCodeInjection */]: "Client Code Injection",
|
|
743
|
+
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: "String Format Misuse"
|
|
735
744
|
};
|
|
736
745
|
var issueTypeZ = z.nativeEnum(IssueType_Enum);
|
|
737
746
|
var getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -1337,9 +1346,7 @@ var progressMassages = {
|
|
|
1337
1346
|
var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
|
|
1338
1347
|
|
|
1339
1348
|
// src/features/analysis/index.ts
|
|
1340
|
-
import crypto from "node:crypto";
|
|
1341
1349
|
import fs4 from "node:fs";
|
|
1342
|
-
import os from "node:os";
|
|
1343
1350
|
import path7 from "node:path";
|
|
1344
1351
|
import { pipeline } from "node:stream/promises";
|
|
1345
1352
|
|
|
@@ -1698,7 +1705,8 @@ var fixDetailsData = {
|
|
|
1698
1705
|
["CLIENT_DOM_STORED_CODE_INJECTION" /* ClientDomStoredCodeInjection */]: {
|
|
1699
1706
|
issueDescription: "Client DOM Stored Code Injection is a client-side security vulnerability where malicious JavaScript code gets stored in the DOM and later executed when retrieved by legitimate scripts.",
|
|
1700
1707
|
fixInstructions: "Update the code to avoid the possibility for malicious JavaScript code to get stored in the DOM."
|
|
1701
|
-
}
|
|
1708
|
+
},
|
|
1709
|
+
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: void 0
|
|
1702
1710
|
};
|
|
1703
1711
|
|
|
1704
1712
|
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
@@ -7444,16 +7452,16 @@ function createSpwan({ args, processPath, name }, options) {
|
|
|
7444
7452
|
return createChildProcess({ childProcess: child, name }, options);
|
|
7445
7453
|
}
|
|
7446
7454
|
function createChildProcess({ childProcess, name }, options) {
|
|
7447
|
-
const
|
|
7455
|
+
const debug17 = Debug12(`mobbdev:${name}`);
|
|
7448
7456
|
const { display } = options;
|
|
7449
7457
|
return new Promise((resolve, reject) => {
|
|
7450
7458
|
let out = "";
|
|
7451
7459
|
const onData = (chunk) => {
|
|
7452
|
-
|
|
7460
|
+
debug17(`chunk received from ${name} std ${chunk}`);
|
|
7453
7461
|
out += chunk;
|
|
7454
7462
|
};
|
|
7455
7463
|
if (!childProcess || !childProcess?.stdout || !childProcess?.stderr) {
|
|
7456
|
-
|
|
7464
|
+
debug17(`unable to fork ${name}`);
|
|
7457
7465
|
reject(new Error(`unable to fork ${name}`));
|
|
7458
7466
|
}
|
|
7459
7467
|
childProcess.stdout?.on("data", onData);
|
|
@@ -7463,11 +7471,11 @@ function createChildProcess({ childProcess, name }, options) {
|
|
|
7463
7471
|
childProcess.stderr?.pipe(process2.stderr);
|
|
7464
7472
|
}
|
|
7465
7473
|
childProcess.on("exit", (code) => {
|
|
7466
|
-
|
|
7474
|
+
debug17(`${name} exit code ${code}`);
|
|
7467
7475
|
resolve({ message: out, code });
|
|
7468
7476
|
});
|
|
7469
7477
|
childProcess.on("error", (err) => {
|
|
7470
|
-
|
|
7478
|
+
debug17(`${name} error %o`, err);
|
|
7471
7479
|
reject(err);
|
|
7472
7480
|
});
|
|
7473
7481
|
});
|
|
@@ -7691,8 +7699,7 @@ async function uploadFile({
|
|
|
7691
7699
|
}
|
|
7692
7700
|
|
|
7693
7701
|
// src/features/analysis/index.ts
|
|
7694
|
-
var { CliError: CliError2, Spinner: Spinner2
|
|
7695
|
-
var webLoginUrl = `${WEB_APP_URL}/cli-login`;
|
|
7702
|
+
var { CliError: CliError2, Spinner: Spinner2 } = utils_exports;
|
|
7696
7703
|
function _getScanSource(command) {
|
|
7697
7704
|
if (command === "review")
|
|
7698
7705
|
return "AUTO_FIXER" /* AutoFixer */;
|
|
@@ -7735,11 +7742,6 @@ async function downloadRepo({
|
|
|
7735
7742
|
repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
|
|
7736
7743
|
return path7.join(dirname, repoRoot);
|
|
7737
7744
|
}
|
|
7738
|
-
var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
|
|
7739
|
-
var LOGIN_CHECK_DELAY = 5 * 1e3;
|
|
7740
|
-
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, ${chalk4.bgBlue(
|
|
7741
|
-
"press any key to continue"
|
|
7742
|
-
)};`;
|
|
7743
7745
|
var getReportUrl = ({
|
|
7744
7746
|
organizationId,
|
|
7745
7747
|
projectId,
|
|
@@ -7896,7 +7898,11 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
7896
7898
|
apiKey: apiKey || config2.get("apiToken"),
|
|
7897
7899
|
type: "apiKey"
|
|
7898
7900
|
});
|
|
7899
|
-
await handleMobbLogin(
|
|
7901
|
+
gqlClient = await handleMobbLogin({
|
|
7902
|
+
inGqlClient: gqlClient,
|
|
7903
|
+
skipPrompts,
|
|
7904
|
+
apiKey
|
|
7905
|
+
});
|
|
7900
7906
|
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId({
|
|
7901
7907
|
projectName: mobbProjectName,
|
|
7902
7908
|
userDefinedOrganizationId: userOrganizationId
|
|
@@ -8038,69 +8044,6 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8038
8044
|
chalk4.bgBlue("\n\n My work here is done for now, see you soon! \u{1F575}\uFE0F\u200D\u2642\uFE0F ")
|
|
8039
8045
|
);
|
|
8040
8046
|
}
|
|
8041
|
-
async function handleMobbLogin() {
|
|
8042
|
-
if (await gqlClient.verifyToken()) {
|
|
8043
|
-
createSpinner4().start().success({
|
|
8044
|
-
text: "\u{1F513} Logged in to Mobb successfully"
|
|
8045
|
-
});
|
|
8046
|
-
return;
|
|
8047
|
-
} else if (apiKey) {
|
|
8048
|
-
createSpinner4().start().error({
|
|
8049
|
-
text: "\u{1F513} Logged in to Mobb failed - check your api-key"
|
|
8050
|
-
});
|
|
8051
|
-
throw new CliError2();
|
|
8052
|
-
}
|
|
8053
|
-
const loginSpinner = createSpinner4().start();
|
|
8054
|
-
if (!skipPrompts) {
|
|
8055
|
-
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
8056
|
-
await keypress2();
|
|
8057
|
-
}
|
|
8058
|
-
loginSpinner.update({
|
|
8059
|
-
text: "\u{1F513} Waiting for Mobb login..."
|
|
8060
|
-
});
|
|
8061
|
-
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
|
|
8062
|
-
modulusLength: 2048
|
|
8063
|
-
});
|
|
8064
|
-
const loginId = await gqlClient.createCliLogin({
|
|
8065
|
-
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
8066
|
-
});
|
|
8067
|
-
const browserUrl = `${webLoginUrl}/${loginId}?hostname=${os.hostname()}`;
|
|
8068
|
-
!ci && console.log(
|
|
8069
|
-
`If the page does not open automatically, kindly access it through ${browserUrl}.`
|
|
8070
|
-
);
|
|
8071
|
-
await open2(browserUrl);
|
|
8072
|
-
let newApiToken = null;
|
|
8073
|
-
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
8074
|
-
const encryptedApiToken = await gqlClient.getEncryptedApiToken({
|
|
8075
|
-
loginId
|
|
8076
|
-
});
|
|
8077
|
-
loginSpinner.spin();
|
|
8078
|
-
if (encryptedApiToken) {
|
|
8079
|
-
debug15("encrypted API token received %s", encryptedApiToken);
|
|
8080
|
-
newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
8081
|
-
debug15("API token decrypted");
|
|
8082
|
-
break;
|
|
8083
|
-
}
|
|
8084
|
-
await sleep(LOGIN_CHECK_DELAY);
|
|
8085
|
-
}
|
|
8086
|
-
if (!newApiToken) {
|
|
8087
|
-
loginSpinner.error({
|
|
8088
|
-
text: "Login timeout error"
|
|
8089
|
-
});
|
|
8090
|
-
throw new CliError2();
|
|
8091
|
-
}
|
|
8092
|
-
gqlClient = new GQLClient({ apiKey: newApiToken, type: "apiKey" });
|
|
8093
|
-
if (await gqlClient.verifyToken()) {
|
|
8094
|
-
debug15("set api token %s", newApiToken);
|
|
8095
|
-
config2.set("apiToken", newApiToken);
|
|
8096
|
-
loginSpinner.success({ text: "\u{1F513} Login to Mobb successful!" });
|
|
8097
|
-
} else {
|
|
8098
|
-
loginSpinner.error({
|
|
8099
|
-
text: "Something went wrong, API token is invalid."
|
|
8100
|
-
});
|
|
8101
|
-
throw new CliError2();
|
|
8102
|
-
}
|
|
8103
|
-
}
|
|
8104
8047
|
async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
|
|
8105
8048
|
const scmLibType = getCloudScmLibTypeFromUrl(repoUrl);
|
|
8106
8049
|
const scmName = scmLibType === "GITHUB" /* GITHUB */ ? "Github" : scmLibType === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType === "ADO" /* ADO */ ? "Azure DevOps" : "";
|
|
@@ -8284,8 +8227,12 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8284
8227
|
}
|
|
8285
8228
|
|
|
8286
8229
|
// src/commands/index.ts
|
|
8230
|
+
import chalk5 from "chalk";
|
|
8287
8231
|
import chalkAnimation from "chalk-animation";
|
|
8288
8232
|
import Configstore2 from "configstore";
|
|
8233
|
+
import Debug17 from "debug";
|
|
8234
|
+
import open3 from "open";
|
|
8235
|
+
var debug16 = Debug17("mobbdev:commands");
|
|
8289
8236
|
async function review(params, { skipPrompts = true } = {}) {
|
|
8290
8237
|
const {
|
|
8291
8238
|
repo,
|
|
@@ -8350,21 +8297,37 @@ async function analyze({
|
|
|
8350
8297
|
}
|
|
8351
8298
|
var config3 = new Configstore2(packageJson.name, { apiToken: "" });
|
|
8352
8299
|
async function addScmToken(addScmTokenOptions) {
|
|
8353
|
-
const { apiKey, token, organization, scmType, url, refreshToken } = addScmTokenOptions;
|
|
8354
|
-
|
|
8300
|
+
const { apiKey, token, organization, scmType, url, refreshToken, ci } = addScmTokenOptions;
|
|
8301
|
+
let gqlClient = new GQLClient({
|
|
8355
8302
|
apiKey: apiKey || config3.get("apiToken"),
|
|
8356
8303
|
type: "apiKey"
|
|
8357
8304
|
});
|
|
8305
|
+
gqlClient = await handleMobbLogin({
|
|
8306
|
+
inGqlClient: gqlClient,
|
|
8307
|
+
skipPrompts: ci,
|
|
8308
|
+
apiKey
|
|
8309
|
+
});
|
|
8358
8310
|
if (!scmType) {
|
|
8359
8311
|
throw new CliError(errorMessages.invalidScmType);
|
|
8360
8312
|
}
|
|
8361
|
-
await gqlClient.updateScmToken({
|
|
8313
|
+
const resp = await gqlClient.updateScmToken({
|
|
8362
8314
|
scmType,
|
|
8363
8315
|
url,
|
|
8364
8316
|
token,
|
|
8365
8317
|
org: organization,
|
|
8366
8318
|
refreshToken
|
|
8367
8319
|
});
|
|
8320
|
+
if (resp.updateScmToken?.__typename === "RepoUnreachableError") {
|
|
8321
|
+
throw new CliError(
|
|
8322
|
+
"Mobb could not reach the repository. Please try again. If Mobb is connected through a broker, please make sure the broker is connected."
|
|
8323
|
+
);
|
|
8324
|
+
} else if (resp.updateScmToken?.__typename === "BadScmCredentials") {
|
|
8325
|
+
throw new CliError("Invalid SCM credentials. Please try again.");
|
|
8326
|
+
} else if (resp.updateScmToken?.__typename === "ScmAccessTokenUpdateSuccess") {
|
|
8327
|
+
console.log("Token added successfully");
|
|
8328
|
+
} else {
|
|
8329
|
+
throw new CliError("Unexpected error, failed to add token");
|
|
8330
|
+
}
|
|
8368
8331
|
}
|
|
8369
8332
|
async function scan(scanOptions, { skipPrompts = false } = {}) {
|
|
8370
8333
|
const { scanner, ci } = scanOptions;
|
|
@@ -8390,34 +8353,109 @@ async function showWelcomeMessage(skipPrompts = false) {
|
|
|
8390
8353
|
skipPrompts ? await sleep(100) : await sleep(2e3);
|
|
8391
8354
|
welcome.stop();
|
|
8392
8355
|
}
|
|
8356
|
+
var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
|
|
8357
|
+
var LOGIN_CHECK_DELAY = 5 * 1e3;
|
|
8358
|
+
var webLoginUrl = `${WEB_APP_URL}/cli-login`;
|
|
8359
|
+
var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk5.bgBlue(
|
|
8360
|
+
"press any key to continue"
|
|
8361
|
+
)};`;
|
|
8362
|
+
async function handleMobbLogin({
|
|
8363
|
+
inGqlClient,
|
|
8364
|
+
apiKey,
|
|
8365
|
+
skipPrompts
|
|
8366
|
+
}) {
|
|
8367
|
+
const { createSpinner: createSpinner4 } = Spinner({ ci: skipPrompts });
|
|
8368
|
+
if (await inGqlClient.verifyToken()) {
|
|
8369
|
+
createSpinner4().start().success({
|
|
8370
|
+
text: "\u{1F513} Logged in to Mobb successfully"
|
|
8371
|
+
});
|
|
8372
|
+
return inGqlClient;
|
|
8373
|
+
} else if (apiKey) {
|
|
8374
|
+
createSpinner4().start().error({
|
|
8375
|
+
text: "\u{1F513} Logged in to Mobb failed - check your api-key"
|
|
8376
|
+
});
|
|
8377
|
+
throw new CliError();
|
|
8378
|
+
}
|
|
8379
|
+
const loginSpinner = createSpinner4().start();
|
|
8380
|
+
if (!skipPrompts) {
|
|
8381
|
+
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
8382
|
+
await keypress();
|
|
8383
|
+
}
|
|
8384
|
+
loginSpinner.update({
|
|
8385
|
+
text: "\u{1F513} Waiting for Mobb login..."
|
|
8386
|
+
});
|
|
8387
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
|
|
8388
|
+
modulusLength: 2048
|
|
8389
|
+
});
|
|
8390
|
+
const loginId = await inGqlClient.createCliLogin({
|
|
8391
|
+
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
8392
|
+
});
|
|
8393
|
+
const browserUrl = `${webLoginUrl}/${loginId}?hostname=${os.hostname()}`;
|
|
8394
|
+
!skipPrompts && console.log(
|
|
8395
|
+
`If the page does not open automatically, kindly access it through ${browserUrl}.`
|
|
8396
|
+
);
|
|
8397
|
+
await open3(browserUrl);
|
|
8398
|
+
let newApiToken = null;
|
|
8399
|
+
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
8400
|
+
const encryptedApiToken = await inGqlClient.getEncryptedApiToken({
|
|
8401
|
+
loginId
|
|
8402
|
+
});
|
|
8403
|
+
loginSpinner.spin();
|
|
8404
|
+
if (encryptedApiToken) {
|
|
8405
|
+
debug16("encrypted API token received %s", encryptedApiToken);
|
|
8406
|
+
newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
8407
|
+
debug16("API token decrypted");
|
|
8408
|
+
break;
|
|
8409
|
+
}
|
|
8410
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
8411
|
+
}
|
|
8412
|
+
if (!newApiToken) {
|
|
8413
|
+
loginSpinner.error({
|
|
8414
|
+
text: "Login timeout error"
|
|
8415
|
+
});
|
|
8416
|
+
throw new CliError();
|
|
8417
|
+
}
|
|
8418
|
+
const newGqlClient = new GQLClient({ apiKey: newApiToken, type: "apiKey" });
|
|
8419
|
+
if (await newGqlClient.verifyToken()) {
|
|
8420
|
+
debug16("set api token %s", newApiToken);
|
|
8421
|
+
config3.set("apiToken", newApiToken);
|
|
8422
|
+
loginSpinner.success({ text: "\u{1F513} Login to Mobb successful!" });
|
|
8423
|
+
} else {
|
|
8424
|
+
loginSpinner.error({
|
|
8425
|
+
text: "Something went wrong, API token is invalid."
|
|
8426
|
+
});
|
|
8427
|
+
throw new CliError();
|
|
8428
|
+
}
|
|
8429
|
+
return newGqlClient;
|
|
8430
|
+
}
|
|
8393
8431
|
|
|
8394
8432
|
// src/args/commands/analyze.ts
|
|
8395
|
-
import
|
|
8433
|
+
import chalk8 from "chalk";
|
|
8396
8434
|
|
|
8397
8435
|
// src/args/options.ts
|
|
8398
|
-
import
|
|
8436
|
+
import chalk6 from "chalk";
|
|
8399
8437
|
var repoOption = {
|
|
8400
8438
|
alias: "r",
|
|
8401
8439
|
demandOption: true,
|
|
8402
8440
|
type: "string",
|
|
8403
|
-
describe:
|
|
8441
|
+
describe: chalk6.bold("Github / GitLab / Azure DevOps repository URL")
|
|
8404
8442
|
};
|
|
8405
8443
|
var projectNameOption = {
|
|
8406
8444
|
type: "string",
|
|
8407
|
-
describe:
|
|
8445
|
+
describe: chalk6.bold("Checkmarx project name (when scanning with Checkmarx)")
|
|
8408
8446
|
};
|
|
8409
8447
|
var yesOption = {
|
|
8410
8448
|
alias: "yes",
|
|
8411
8449
|
type: "boolean",
|
|
8412
|
-
describe:
|
|
8450
|
+
describe: chalk6.bold("Skip prompts and use default values")
|
|
8413
8451
|
};
|
|
8414
8452
|
var refOption = {
|
|
8415
|
-
describe:
|
|
8453
|
+
describe: chalk6.bold("reference of the repository (branch, tag, commit)"),
|
|
8416
8454
|
type: "string",
|
|
8417
8455
|
demandOption: false
|
|
8418
8456
|
};
|
|
8419
8457
|
var organizationIdOptions = {
|
|
8420
|
-
describe:
|
|
8458
|
+
describe: chalk6.bold("Organization id"),
|
|
8421
8459
|
alias: "organization-id",
|
|
8422
8460
|
type: "string",
|
|
8423
8461
|
demandOption: false
|
|
@@ -8425,15 +8463,15 @@ var organizationIdOptions = {
|
|
|
8425
8463
|
var scannerOptions = {
|
|
8426
8464
|
alias: "s",
|
|
8427
8465
|
choices: Object.values(SCANNERS),
|
|
8428
|
-
describe:
|
|
8466
|
+
describe: chalk6.bold("Select the scanner to use")
|
|
8429
8467
|
};
|
|
8430
8468
|
var mobbProjectNameOption = {
|
|
8431
8469
|
type: "string",
|
|
8432
|
-
describe:
|
|
8470
|
+
describe: chalk6.bold("Mobb project name"),
|
|
8433
8471
|
default: PROJECT_DEFAULT_NAME
|
|
8434
8472
|
};
|
|
8435
8473
|
var ciOption = {
|
|
8436
|
-
describe:
|
|
8474
|
+
describe: chalk6.bold(
|
|
8437
8475
|
"Run in CI mode, prompts and browser will not be opened"
|
|
8438
8476
|
),
|
|
8439
8477
|
type: "boolean",
|
|
@@ -8441,46 +8479,46 @@ var ciOption = {
|
|
|
8441
8479
|
};
|
|
8442
8480
|
var apiKeyOption = {
|
|
8443
8481
|
type: "string",
|
|
8444
|
-
describe:
|
|
8482
|
+
describe: chalk6.bold("Mobb authentication api-key")
|
|
8445
8483
|
};
|
|
8446
8484
|
var commitHashOption = {
|
|
8447
8485
|
alias: "ch",
|
|
8448
|
-
describe:
|
|
8486
|
+
describe: chalk6.bold("Hash of the commit"),
|
|
8449
8487
|
type: "string"
|
|
8450
8488
|
};
|
|
8451
8489
|
var autoPrOption = {
|
|
8452
|
-
describe:
|
|
8490
|
+
describe: chalk6.bold("Enable automatic pull requests for new fixes"),
|
|
8453
8491
|
type: "boolean",
|
|
8454
8492
|
default: false
|
|
8455
8493
|
};
|
|
8456
8494
|
var scmTypeOption = {
|
|
8457
8495
|
demandOption: true,
|
|
8458
|
-
describe:
|
|
8496
|
+
describe: chalk6.bold("SCM type"),
|
|
8459
8497
|
choices: Object.values(ScmType)
|
|
8460
8498
|
};
|
|
8461
8499
|
var urlOption = {
|
|
8462
|
-
describe:
|
|
8500
|
+
describe: chalk6.bold(
|
|
8463
8501
|
`URL of the repository (used in ${Object.values(ScmType).join(", ")})`
|
|
8464
8502
|
),
|
|
8465
8503
|
type: "string",
|
|
8466
8504
|
demandOption: true
|
|
8467
8505
|
};
|
|
8468
8506
|
var scmOrgOption = {
|
|
8469
|
-
describe:
|
|
8507
|
+
describe: chalk6.bold("Organization name in SCM (used in Azure DevOps)"),
|
|
8470
8508
|
type: "string"
|
|
8471
8509
|
};
|
|
8472
8510
|
var scmRefreshTokenOption = {
|
|
8473
|
-
describe:
|
|
8511
|
+
describe: chalk6.bold("SCM refresh token (used in GitLab)"),
|
|
8474
8512
|
type: "string"
|
|
8475
8513
|
};
|
|
8476
8514
|
var scmTokenOption = {
|
|
8477
|
-
describe:
|
|
8515
|
+
describe: chalk6.bold("SCM API token"),
|
|
8478
8516
|
type: "string",
|
|
8479
8517
|
demandOption: true
|
|
8480
8518
|
};
|
|
8481
8519
|
|
|
8482
8520
|
// src/args/validation.ts
|
|
8483
|
-
import
|
|
8521
|
+
import chalk7 from "chalk";
|
|
8484
8522
|
import path8 from "path";
|
|
8485
8523
|
import { z as z23 } from "zod";
|
|
8486
8524
|
function throwRepoUrlErrorMessage({
|
|
@@ -8490,11 +8528,11 @@ function throwRepoUrlErrorMessage({
|
|
|
8490
8528
|
}) {
|
|
8491
8529
|
const errorMessage = error.issues[error.issues.length - 1]?.message;
|
|
8492
8530
|
const formattedErrorMessage = `
|
|
8493
|
-
Error: ${
|
|
8531
|
+
Error: ${chalk7.bold(
|
|
8494
8532
|
repoUrl
|
|
8495
8533
|
)} is ${errorMessage}
|
|
8496
8534
|
Example:
|
|
8497
|
-
mobbdev ${command} -r ${
|
|
8535
|
+
mobbdev ${command} -r ${chalk7.bold(
|
|
8498
8536
|
"https://github.com/WebGoat/WebGoat"
|
|
8499
8537
|
)}`;
|
|
8500
8538
|
throw new CliError(formattedErrorMessage);
|
|
@@ -8528,9 +8566,9 @@ function validateReportFileFormat(reportFile) {
|
|
|
8528
8566
|
if (!supportExtensions.includes(path8.extname(reportFile))) {
|
|
8529
8567
|
throw new CliError(
|
|
8530
8568
|
`
|
|
8531
|
-
${
|
|
8569
|
+
${chalk7.bold(
|
|
8532
8570
|
reportFile
|
|
8533
|
-
)} is not a supported file extension. Supported extensions are: ${
|
|
8571
|
+
)} is not a supported file extension. Supported extensions are: ${chalk7.bold(
|
|
8534
8572
|
supportExtensions.join(", ")
|
|
8535
8573
|
)}
|
|
8536
8574
|
`
|
|
@@ -8544,18 +8582,18 @@ function analyzeBuilder(yargs2) {
|
|
|
8544
8582
|
alias: "scan-file",
|
|
8545
8583
|
demandOption: true,
|
|
8546
8584
|
type: "string",
|
|
8547
|
-
describe:
|
|
8585
|
+
describe: chalk8.bold(
|
|
8548
8586
|
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube)"
|
|
8549
8587
|
)
|
|
8550
8588
|
}).option("repo", repoOption).option("p", {
|
|
8551
8589
|
alias: "src-path",
|
|
8552
|
-
describe:
|
|
8590
|
+
describe: chalk8.bold(
|
|
8553
8591
|
"Path to the repository folder with the source code"
|
|
8554
8592
|
),
|
|
8555
8593
|
type: "string"
|
|
8556
8594
|
}).option("ref", refOption).option("ch", {
|
|
8557
8595
|
alias: "commit-hash",
|
|
8558
|
-
describe:
|
|
8596
|
+
describe: chalk8.bold("Hash of the commit"),
|
|
8559
8597
|
type: "string"
|
|
8560
8598
|
}).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("org", organizationIdOptions).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).option("auto-pr", autoPrOption).example(
|
|
8561
8599
|
"$0 analyze -r https://github.com/WebGoat/WebGoat -f <your_vulirabitliy_report_path>",
|
|
@@ -8565,7 +8603,7 @@ function analyzeBuilder(yargs2) {
|
|
|
8565
8603
|
function validateAnalyzeOptions(argv) {
|
|
8566
8604
|
if (!fs5.existsSync(argv.f)) {
|
|
8567
8605
|
throw new CliError(`
|
|
8568
|
-
Can't access ${
|
|
8606
|
+
Can't access ${chalk8.bold(argv.f)}`);
|
|
8569
8607
|
}
|
|
8570
8608
|
validateOrganizationId(argv.organizationId);
|
|
8571
8609
|
if (!argv.srcPath && !argv.repo) {
|
|
@@ -8586,32 +8624,32 @@ async function analyzeHandler(args) {
|
|
|
8586
8624
|
|
|
8587
8625
|
// src/args/commands/review.ts
|
|
8588
8626
|
import fs6 from "node:fs";
|
|
8589
|
-
import
|
|
8627
|
+
import chalk9 from "chalk";
|
|
8590
8628
|
function reviewBuilder(yargs2) {
|
|
8591
8629
|
return yargs2.option("f", {
|
|
8592
8630
|
alias: "scan-file",
|
|
8593
8631
|
demandOption: true,
|
|
8594
8632
|
type: "string",
|
|
8595
|
-
describe:
|
|
8633
|
+
describe: chalk9.bold(
|
|
8596
8634
|
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube)"
|
|
8597
8635
|
)
|
|
8598
8636
|
}).option("repo", { ...repoOption, demandOption: true }).option("scanner", { ...scannerOptions, demandOption: true }).option("ref", { ...refOption, demandOption: true }).option("ch", {
|
|
8599
8637
|
alias: "commit-hash",
|
|
8600
|
-
describe:
|
|
8638
|
+
describe: chalk9.bold("Hash of the commit"),
|
|
8601
8639
|
type: "string",
|
|
8602
8640
|
demandOption: true
|
|
8603
8641
|
}).option("mobb-project-name", mobbProjectNameOption).option("api-key", { ...apiKeyOption, demandOption: true }).option("commit-hash", { ...commitHashOption, demandOption: true }).option("github-token", {
|
|
8604
|
-
describe:
|
|
8642
|
+
describe: chalk9.bold("Github action token"),
|
|
8605
8643
|
type: "string",
|
|
8606
8644
|
demandOption: true
|
|
8607
8645
|
}).option("pull-request", {
|
|
8608
8646
|
alias: "pr",
|
|
8609
|
-
describe:
|
|
8647
|
+
describe: chalk9.bold("Number of the pull request"),
|
|
8610
8648
|
type: "number",
|
|
8611
8649
|
demandOption: true
|
|
8612
8650
|
}).option("p", {
|
|
8613
8651
|
alias: "src-path",
|
|
8614
|
-
describe:
|
|
8652
|
+
describe: chalk9.bold(
|
|
8615
8653
|
"Path to the repository folder with the source code"
|
|
8616
8654
|
),
|
|
8617
8655
|
type: "string",
|
|
@@ -8624,7 +8662,7 @@ function reviewBuilder(yargs2) {
|
|
|
8624
8662
|
function validateReviewOptions(argv) {
|
|
8625
8663
|
if (!fs6.existsSync(argv.f)) {
|
|
8626
8664
|
throw new CliError(`
|
|
8627
|
-
Can't access ${
|
|
8665
|
+
Can't access ${chalk9.bold(argv.f)}`);
|
|
8628
8666
|
}
|
|
8629
8667
|
validateRepoUrl(argv);
|
|
8630
8668
|
validateReportFileFormat(argv.f);
|
|
@@ -8661,7 +8699,7 @@ async function scanHandler(args) {
|
|
|
8661
8699
|
|
|
8662
8700
|
// src/args/commands/token.ts
|
|
8663
8701
|
function addScmTokenBuilder(args) {
|
|
8664
|
-
return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
|
|
8702
|
+
return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).option("ci", ciOption).example(
|
|
8665
8703
|
"$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
|
|
8666
8704
|
`Add your SCM (${Object.values(scmFriendlyText).join(", ")}) token to Mobb to enable automated fixes.`
|
|
8667
8705
|
).help().demandOption(["url", "token"]);
|
|
@@ -8698,42 +8736,42 @@ async function addScmTokenHandler(args) {
|
|
|
8698
8736
|
var parseArgs = async (args) => {
|
|
8699
8737
|
const yargsInstance = yargs(args);
|
|
8700
8738
|
return yargsInstance.updateStrings({
|
|
8701
|
-
"Commands:":
|
|
8702
|
-
"Options:":
|
|
8703
|
-
"Examples:":
|
|
8704
|
-
"Show help":
|
|
8739
|
+
"Commands:": chalk10.yellow.underline.bold("Commands:"),
|
|
8740
|
+
"Options:": chalk10.yellow.underline.bold("Options:"),
|
|
8741
|
+
"Examples:": chalk10.yellow.underline.bold("Examples:"),
|
|
8742
|
+
"Show help": chalk10.bold("Show help")
|
|
8705
8743
|
}).usage(
|
|
8706
|
-
`${
|
|
8744
|
+
`${chalk10.bold(
|
|
8707
8745
|
"\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
|
|
8708
|
-
)} ${
|
|
8709
|
-
$0 ${
|
|
8746
|
+
)} ${chalk10.yellow.underline.bold("Usage:")}
|
|
8747
|
+
$0 ${chalk10.green(
|
|
8710
8748
|
"<command>"
|
|
8711
|
-
)} ${
|
|
8749
|
+
)} ${chalk10.dim("[options]")}
|
|
8712
8750
|
`
|
|
8713
8751
|
).version(false).command(
|
|
8714
8752
|
mobbCliCommand.scan,
|
|
8715
|
-
|
|
8753
|
+
chalk10.bold(
|
|
8716
8754
|
"Scan your code for vulnerabilities, get automated fixes right away."
|
|
8717
8755
|
),
|
|
8718
8756
|
scanBuilder,
|
|
8719
8757
|
scanHandler
|
|
8720
8758
|
).command(
|
|
8721
8759
|
mobbCliCommand.analyze,
|
|
8722
|
-
|
|
8760
|
+
chalk10.bold(
|
|
8723
8761
|
"Provide a vulnerability report and relevant code repository, get automated fixes right away."
|
|
8724
8762
|
),
|
|
8725
8763
|
analyzeBuilder,
|
|
8726
8764
|
analyzeHandler
|
|
8727
8765
|
).command(
|
|
8728
8766
|
mobbCliCommand.review,
|
|
8729
|
-
|
|
8767
|
+
chalk10.bold(
|
|
8730
8768
|
"Mobb will review your github pull requests and provide comments with fixes "
|
|
8731
8769
|
),
|
|
8732
8770
|
reviewBuilder,
|
|
8733
8771
|
reviewHandler
|
|
8734
8772
|
).command(
|
|
8735
8773
|
mobbCliCommand.addScmToken,
|
|
8736
|
-
|
|
8774
|
+
chalk10.bold(
|
|
8737
8775
|
"Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
|
|
8738
8776
|
),
|
|
8739
8777
|
addScmTokenBuilder,
|
|
@@ -8746,7 +8784,7 @@ var parseArgs = async (args) => {
|
|
|
8746
8784
|
handler() {
|
|
8747
8785
|
yargsInstance.showHelp();
|
|
8748
8786
|
}
|
|
8749
|
-
}).strictOptions().help("h").alias("h", "help").epilog(
|
|
8787
|
+
}).strictOptions().help("h").alias("h", "help").epilog(chalk10.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
|
|
8750
8788
|
};
|
|
8751
8789
|
|
|
8752
8790
|
// src/index.ts
|