mobbdev 1.0.2 → 1.0.4
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 +102 -63
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -148,6 +148,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
148
148
|
IssueType_Enum2["MissingEqualsOrHashcode"] = "MISSING_EQUALS_OR_HASHCODE";
|
|
149
149
|
IssueType_Enum2["MissingHstsHeader"] = "MISSING_HSTS_HEADER";
|
|
150
150
|
IssueType_Enum2["NonFinalPublicStaticField"] = "NON_FINAL_PUBLIC_STATIC_FIELD";
|
|
151
|
+
IssueType_Enum2["NonReadonlyField"] = "NON_READONLY_FIELD";
|
|
151
152
|
IssueType_Enum2["NoEquivalenceMethod"] = "NO_EQUIVALENCE_METHOD";
|
|
152
153
|
IssueType_Enum2["NoLimitsOrThrottling"] = "NO_LIMITS_OR_THROTTLING";
|
|
153
154
|
IssueType_Enum2["NullDereference"] = "NULL_DEREFERENCE";
|
|
@@ -740,7 +741,8 @@ var issueTypeMap = {
|
|
|
740
741
|
["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: "Hardcoded Domain in HTML",
|
|
741
742
|
["HEAP_INSPECTION" /* HeapInspection */]: "Heap Inspection",
|
|
742
743
|
["CLIENT_DOM_STORED_CODE_INJECTION" /* ClientDomStoredCodeInjection */]: "Client Code Injection",
|
|
743
|
-
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: "String Format Misuse"
|
|
744
|
+
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: "String Format Misuse",
|
|
745
|
+
["NON_READONLY_FIELD" /* NonReadonlyField */]: "Non Readonly Field"
|
|
744
746
|
};
|
|
745
747
|
var issueTypeZ = z.nativeEnum(IssueType_Enum);
|
|
746
748
|
var getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -1435,6 +1437,7 @@ import chalk4 from "chalk";
|
|
|
1435
1437
|
import Configstore from "configstore";
|
|
1436
1438
|
import Debug16 from "debug";
|
|
1437
1439
|
import extract from "extract-zip";
|
|
1440
|
+
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
1438
1441
|
import fetch4 from "node-fetch";
|
|
1439
1442
|
import open2 from "open";
|
|
1440
1443
|
import tmp2 from "tmp";
|
|
@@ -1467,8 +1470,8 @@ import { z as z16 } from "zod";
|
|
|
1467
1470
|
|
|
1468
1471
|
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
1469
1472
|
import querystring from "node:querystring";
|
|
1470
|
-
import bitbucketPkg from "bitbucket";
|
|
1471
1473
|
import * as bitbucketPkgNode from "bitbucket";
|
|
1474
|
+
import bitbucketPkg from "bitbucket";
|
|
1472
1475
|
import Debug2 from "debug";
|
|
1473
1476
|
import { z as z12 } from "zod";
|
|
1474
1477
|
|
|
@@ -1706,7 +1709,8 @@ var fixDetailsData = {
|
|
|
1706
1709
|
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.",
|
|
1707
1710
|
fixInstructions: "Update the code to avoid the possibility for malicious JavaScript code to get stored in the DOM."
|
|
1708
1711
|
},
|
|
1709
|
-
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: void 0
|
|
1712
|
+
["STRING_FORMAT_MISUSE" /* StringFormatMisuse */]: void 0,
|
|
1713
|
+
["NON_READONLY_FIELD" /* NonReadonlyField */]: void 0
|
|
1710
1714
|
};
|
|
1711
1715
|
|
|
1712
1716
|
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
@@ -3651,7 +3655,10 @@ async function validateBitbucketParams(params) {
|
|
|
3651
3655
|
throw new InvalidRepoUrlError(safeParseError.data.error.error.message);
|
|
3652
3656
|
}
|
|
3653
3657
|
}
|
|
3654
|
-
|
|
3658
|
+
console.log("validateBitbucketParams error", e);
|
|
3659
|
+
throw new InvalidRepoUrlError(
|
|
3660
|
+
`cannot access BB repo URL: ${params.url} with the provided access token`
|
|
3661
|
+
);
|
|
3655
3662
|
}
|
|
3656
3663
|
}
|
|
3657
3664
|
async function getUsersworkspacesSlugs(bitbucketClient) {
|
|
@@ -3824,7 +3831,10 @@ async function githubValidateParams(url, accessToken) {
|
|
|
3824
3831
|
if (code === 404) {
|
|
3825
3832
|
throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
|
|
3826
3833
|
}
|
|
3827
|
-
|
|
3834
|
+
console.log("githubValidateParams error", e);
|
|
3835
|
+
throw new InvalidRepoUrlError(
|
|
3836
|
+
`cannot access GH repo URL: ${url} with the provided access token`
|
|
3837
|
+
);
|
|
3828
3838
|
}
|
|
3829
3839
|
}
|
|
3830
3840
|
|
|
@@ -4260,7 +4270,10 @@ async function gitlabValidateParams({
|
|
|
4260
4270
|
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
4261
4271
|
throw new InvalidRepoUrlError(`invalid gitlab repo URL: ${url}`);
|
|
4262
4272
|
}
|
|
4263
|
-
|
|
4273
|
+
console.log("gitlabValidateParams error", e);
|
|
4274
|
+
throw new InvalidRepoUrlError(
|
|
4275
|
+
`cannot access gitlab repo URL: ${url} with the provided access token`
|
|
4276
|
+
);
|
|
4264
4277
|
}
|
|
4265
4278
|
}
|
|
4266
4279
|
async function getGitlabUsername(url, accessToken) {
|
|
@@ -5997,7 +6010,10 @@ async function adoValidateParams({
|
|
|
5997
6010
|
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
5998
6011
|
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
5999
6012
|
}
|
|
6000
|
-
|
|
6013
|
+
console.log("adoValidateParams error", e);
|
|
6014
|
+
throw new InvalidRepoUrlError(
|
|
6015
|
+
`cannot access ADO repo URL: ${url} with the provided access token`
|
|
6016
|
+
);
|
|
6001
6017
|
}
|
|
6002
6018
|
}
|
|
6003
6019
|
async function getOrgsForOauthToken({
|
|
@@ -6802,8 +6818,8 @@ async function addFixCommentsForPr({
|
|
|
6802
6818
|
import Debug8 from "debug";
|
|
6803
6819
|
var debug8 = Debug8("mobbdev:handleAutoPr");
|
|
6804
6820
|
async function handleAutoPr(params) {
|
|
6805
|
-
const { gqlClient, analysisId, createSpinner:
|
|
6806
|
-
const createAutoPrSpinner =
|
|
6821
|
+
const { gqlClient, analysisId, createSpinner: createSpinner5 } = params;
|
|
6822
|
+
const createAutoPrSpinner = createSpinner5(
|
|
6807
6823
|
"\u{1F504} Waiting for the analysis to finish before initiating automatic pull request creation"
|
|
6808
6824
|
).start();
|
|
6809
6825
|
return await gqlClient.subscribeToAnalysis({
|
|
@@ -7712,8 +7728,8 @@ async function downloadRepo({
|
|
|
7712
7728
|
dirname,
|
|
7713
7729
|
ci
|
|
7714
7730
|
}) {
|
|
7715
|
-
const { createSpinner:
|
|
7716
|
-
const repoSpinner =
|
|
7731
|
+
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
7732
|
+
const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
|
|
7717
7733
|
debug15("download repo %s %s %s", repoUrl, dirname);
|
|
7718
7734
|
const zipFilePath = path7.join(dirname, "repo.zip");
|
|
7719
7735
|
debug15("download URL: %s auth headers: %o", downloadUrl, authHeaders);
|
|
@@ -7892,7 +7908,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
7892
7908
|
autoPr
|
|
7893
7909
|
} = params;
|
|
7894
7910
|
debug15("start %s %s", dirname, repo);
|
|
7895
|
-
const { createSpinner:
|
|
7911
|
+
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
7896
7912
|
skipPrompts = skipPrompts || ci;
|
|
7897
7913
|
let gqlClient = new GQLClient({
|
|
7898
7914
|
apiKey: apiKey || config2.get("apiToken"),
|
|
@@ -7929,7 +7945,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
7929
7945
|
});
|
|
7930
7946
|
if (!isRepoAvailable) {
|
|
7931
7947
|
if (ci || !cloudScmLibType || !scmAuthUrl) {
|
|
7932
|
-
const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}
|
|
7948
|
+
const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}. Make sure that the repo is accessible and the SCM token configured on Mobb is correct.` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
|
|
7933
7949
|
throw new Error(errorMessage);
|
|
7934
7950
|
}
|
|
7935
7951
|
if (cloudScmLibType && scmAuthUrl) {
|
|
@@ -7982,7 +7998,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
7982
7998
|
if (!reportPath) {
|
|
7983
7999
|
throw new Error("reportPath is null");
|
|
7984
8000
|
}
|
|
7985
|
-
const uploadReportSpinner =
|
|
8001
|
+
const uploadReportSpinner = createSpinner5("\u{1F4C1} Uploading Report").start();
|
|
7986
8002
|
try {
|
|
7987
8003
|
await uploadFile({
|
|
7988
8004
|
file: reportPath,
|
|
@@ -7994,8 +8010,14 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
7994
8010
|
uploadReportSpinner.error({ text: "\u{1F4C1} Report upload failed" });
|
|
7995
8011
|
throw e;
|
|
7996
8012
|
}
|
|
8013
|
+
await _digestReport({
|
|
8014
|
+
gqlClient,
|
|
8015
|
+
fixReportId: reportUploadInfo.fixReportId,
|
|
8016
|
+
projectId,
|
|
8017
|
+
command
|
|
8018
|
+
});
|
|
7997
8019
|
uploadReportSpinner.success({ text: "\u{1F4C1} Report uploaded successfully" });
|
|
7998
|
-
const mobbSpinner =
|
|
8020
|
+
const mobbSpinner = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
7999
8021
|
const sendReportRes = await sendReport({
|
|
8000
8022
|
gqlClient,
|
|
8001
8023
|
spinner: mobbSpinner,
|
|
@@ -8022,7 +8044,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8022
8044
|
await handleAutoPr({
|
|
8023
8045
|
gqlClient,
|
|
8024
8046
|
analysisId: reportUploadInfo.fixReportId,
|
|
8025
|
-
createSpinner:
|
|
8047
|
+
createSpinner: createSpinner5
|
|
8026
8048
|
});
|
|
8027
8049
|
}
|
|
8028
8050
|
await askToOpenAnalysis();
|
|
@@ -8048,7 +8070,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8048
8070
|
const scmLibType = getCloudScmLibTypeFromUrl(repoUrl);
|
|
8049
8071
|
const scmName = scmLibType === "GITHUB" /* GITHUB */ ? "Github" : scmLibType === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType === "ADO" /* ADO */ ? "Azure DevOps" : "";
|
|
8050
8072
|
const addScmIntegration = skipPrompts ? true : await scmIntegrationPrompt(scmName);
|
|
8051
|
-
const scmSpinner =
|
|
8073
|
+
const scmSpinner = createSpinner5(
|
|
8052
8074
|
`\u{1F517} Waiting for ${scmName} integration...`
|
|
8053
8075
|
).start();
|
|
8054
8076
|
if (!addScmIntegration) {
|
|
@@ -8092,7 +8114,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8092
8114
|
if (!srcPath || !reportPath) {
|
|
8093
8115
|
throw new Error("src path and reportPath is required");
|
|
8094
8116
|
}
|
|
8095
|
-
const uploadReportSpinner2 =
|
|
8117
|
+
const uploadReportSpinner2 = createSpinner5("\u{1F4C1} Uploading Report").start();
|
|
8096
8118
|
try {
|
|
8097
8119
|
await uploadFile({
|
|
8098
8120
|
file: reportPath,
|
|
@@ -8107,48 +8129,17 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8107
8129
|
uploadReportSpinner2.success({
|
|
8108
8130
|
text: "\u{1F4C1} Uploading Report successful!"
|
|
8109
8131
|
});
|
|
8110
|
-
const
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
try {
|
|
8116
|
-
const { vulnerabilityReportId } = await gqlClient.digestVulnerabilityReport({
|
|
8117
|
-
fixReportId: reportUploadInfo.fixReportId,
|
|
8118
|
-
projectId,
|
|
8119
|
-
scanSource: _getScanSource(command)
|
|
8120
|
-
});
|
|
8121
|
-
try {
|
|
8122
|
-
await gqlClient.subscribeToAnalysis({
|
|
8123
|
-
subscribeToAnalysisParams: {
|
|
8124
|
-
analysisId: reportUploadInfo.fixReportId
|
|
8125
|
-
},
|
|
8126
|
-
callback: () => digestSpinner.update({
|
|
8127
|
-
text: progressMassages.processingVulnerabilityReportSuccess
|
|
8128
|
-
}),
|
|
8129
|
-
callbackStates: [
|
|
8130
|
-
"Digested" /* Digested */,
|
|
8131
|
-
"Finished" /* Finished */
|
|
8132
|
-
],
|
|
8133
|
-
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
8134
|
-
});
|
|
8135
|
-
} catch (e) {
|
|
8136
|
-
throw new Error(progressMassages.processingVulnerabilityReportFailed);
|
|
8137
|
-
}
|
|
8138
|
-
vulnFiles = await gqlClient.getVulnerabilityReportPaths(
|
|
8139
|
-
vulnerabilityReportId
|
|
8140
|
-
);
|
|
8141
|
-
} catch (e) {
|
|
8142
|
-
digestSpinner.error({ text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Digesting report failed" });
|
|
8143
|
-
throw e;
|
|
8144
|
-
}
|
|
8145
|
-
digestSpinner.success({
|
|
8146
|
-
text: progressMassages.processingVulnerabilityReportSuccess
|
|
8132
|
+
const vulnFiles = await _digestReport({
|
|
8133
|
+
gqlClient,
|
|
8134
|
+
fixReportId: reportUploadInfo.fixReportId,
|
|
8135
|
+
projectId,
|
|
8136
|
+
command
|
|
8147
8137
|
});
|
|
8148
|
-
const
|
|
8138
|
+
const gitInfo = await getGitInfo(srcPath);
|
|
8139
|
+
const zippingSpinner = createSpinner5("\u{1F4E6} Zipping repo").start();
|
|
8149
8140
|
const zipBuffer = await pack(srcPath, vulnFiles);
|
|
8150
8141
|
zippingSpinner.success({ text: "\u{1F4E6} Zipping repo successful!" });
|
|
8151
|
-
const uploadRepoSpinner =
|
|
8142
|
+
const uploadRepoSpinner = createSpinner5("\u{1F4C1} Uploading Repo").start();
|
|
8152
8143
|
try {
|
|
8153
8144
|
await uploadFile({
|
|
8154
8145
|
file: zipBuffer,
|
|
@@ -8161,7 +8152,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8161
8152
|
throw e;
|
|
8162
8153
|
}
|
|
8163
8154
|
uploadRepoSpinner.success({ text: "\u{1F4C1} Uploading Repo successful!" });
|
|
8164
|
-
const mobbSpinner2 =
|
|
8155
|
+
const mobbSpinner2 = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
8165
8156
|
try {
|
|
8166
8157
|
await sendReport({
|
|
8167
8158
|
gqlClient,
|
|
@@ -8218,13 +8209,61 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8218
8209
|
await handleAutoPr({
|
|
8219
8210
|
gqlClient,
|
|
8220
8211
|
analysisId: reportUploadInfo.fixReportId,
|
|
8221
|
-
createSpinner:
|
|
8212
|
+
createSpinner: createSpinner5
|
|
8222
8213
|
});
|
|
8223
8214
|
}
|
|
8224
8215
|
await askToOpenAnalysis();
|
|
8225
8216
|
return reportUploadInfo.fixReportId;
|
|
8226
8217
|
}
|
|
8227
8218
|
}
|
|
8219
|
+
async function _digestReport({
|
|
8220
|
+
gqlClient,
|
|
8221
|
+
fixReportId,
|
|
8222
|
+
projectId,
|
|
8223
|
+
command
|
|
8224
|
+
}) {
|
|
8225
|
+
const digestSpinner = createSpinner4(
|
|
8226
|
+
progressMassages.processingVulnerabilityReport
|
|
8227
|
+
).start();
|
|
8228
|
+
try {
|
|
8229
|
+
const { vulnerabilityReportId } = await gqlClient.digestVulnerabilityReport(
|
|
8230
|
+
{
|
|
8231
|
+
fixReportId,
|
|
8232
|
+
projectId,
|
|
8233
|
+
scanSource: _getScanSource(command)
|
|
8234
|
+
}
|
|
8235
|
+
);
|
|
8236
|
+
try {
|
|
8237
|
+
await gqlClient.subscribeToAnalysis({
|
|
8238
|
+
subscribeToAnalysisParams: {
|
|
8239
|
+
analysisId: fixReportId
|
|
8240
|
+
},
|
|
8241
|
+
callback: () => digestSpinner.update({
|
|
8242
|
+
text: progressMassages.processingVulnerabilityReportSuccess
|
|
8243
|
+
}),
|
|
8244
|
+
callbackStates: [
|
|
8245
|
+
"Digested" /* Digested */,
|
|
8246
|
+
"Finished" /* Finished */
|
|
8247
|
+
],
|
|
8248
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
8249
|
+
});
|
|
8250
|
+
} catch (e) {
|
|
8251
|
+
throw new Error(progressMassages.processingVulnerabilityReportFailed);
|
|
8252
|
+
}
|
|
8253
|
+
const vulnFiles = await gqlClient.getVulnerabilityReportPaths(
|
|
8254
|
+
vulnerabilityReportId
|
|
8255
|
+
);
|
|
8256
|
+
digestSpinner.success({
|
|
8257
|
+
text: progressMassages.processingVulnerabilityReportSuccess
|
|
8258
|
+
});
|
|
8259
|
+
return vulnFiles;
|
|
8260
|
+
} catch (e) {
|
|
8261
|
+
digestSpinner.error({
|
|
8262
|
+
text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Digesting report failed. Please verify that the file provided is of a valid supported report format."
|
|
8263
|
+
});
|
|
8264
|
+
throw e;
|
|
8265
|
+
}
|
|
8266
|
+
}
|
|
8228
8267
|
|
|
8229
8268
|
// src/commands/index.ts
|
|
8230
8269
|
import chalk5 from "chalk";
|
|
@@ -8364,19 +8403,19 @@ async function handleMobbLogin({
|
|
|
8364
8403
|
apiKey,
|
|
8365
8404
|
skipPrompts
|
|
8366
8405
|
}) {
|
|
8367
|
-
const { createSpinner:
|
|
8406
|
+
const { createSpinner: createSpinner5 } = Spinner({ ci: skipPrompts });
|
|
8368
8407
|
if (await inGqlClient.verifyToken()) {
|
|
8369
|
-
|
|
8408
|
+
createSpinner5().start().success({
|
|
8370
8409
|
text: "\u{1F513} Logged in to Mobb successfully"
|
|
8371
8410
|
});
|
|
8372
8411
|
return inGqlClient;
|
|
8373
8412
|
} else if (apiKey) {
|
|
8374
|
-
|
|
8413
|
+
createSpinner5().start().error({
|
|
8375
8414
|
text: "\u{1F513} Logged in to Mobb failed - check your api-key"
|
|
8376
8415
|
});
|
|
8377
8416
|
throw new CliError();
|
|
8378
8417
|
}
|
|
8379
|
-
const loginSpinner =
|
|
8418
|
+
const loginSpinner = createSpinner5().start();
|
|
8380
8419
|
if (!skipPrompts) {
|
|
8381
8420
|
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
8382
8421
|
await keypress();
|