mobbdev 0.0.30 → 0.0.32
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.js +116 -33
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -69,6 +69,7 @@ var WEB_APP_URL = envVariables.WEB_APP_URL;
|
|
|
69
69
|
var API_URL = envVariables.API_URL;
|
|
70
70
|
|
|
71
71
|
// src/features/analysis/index.ts
|
|
72
|
+
import crypto from "node:crypto";
|
|
72
73
|
import fs3 from "node:fs";
|
|
73
74
|
import path5 from "node:path";
|
|
74
75
|
|
|
@@ -408,6 +409,20 @@ var CREATE_COMMUNITY_USER = gql`
|
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
411
|
`;
|
|
412
|
+
var CREATE_CLI_LOGIN = gql`
|
|
413
|
+
mutation CreateCliLogin($publicKey: String!) {
|
|
414
|
+
insert_cli_login_one(object: { publicKey: $publicKey }) {
|
|
415
|
+
id
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
`;
|
|
419
|
+
var PERFORM_CLI_LOGIN = gql`
|
|
420
|
+
mutation performCliLogin($loginId: String!) {
|
|
421
|
+
performCliLogin(loginId: $loginId) {
|
|
422
|
+
status
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
`;
|
|
411
426
|
|
|
412
427
|
// src/features/analysis/graphql/queries.ts
|
|
413
428
|
import { gql as gql2 } from "graphql-request";
|
|
@@ -434,6 +449,13 @@ var GET_ORG_AND_PROJECT_ID = gql2`
|
|
|
434
449
|
}
|
|
435
450
|
}
|
|
436
451
|
`;
|
|
452
|
+
var GET_ENCRYPTED_API_TOKEN = gql2`
|
|
453
|
+
query GetEncryptedApiToken($loginId: uuid!) {
|
|
454
|
+
cli_login_by_pk(id: $loginId) {
|
|
455
|
+
encryptedApiToken
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
`;
|
|
437
459
|
|
|
438
460
|
// src/features/analysis/graphql/types.ts
|
|
439
461
|
import { z as z3 } from "zod";
|
|
@@ -487,22 +509,40 @@ var GetOrgAndProjectIdQueryZ = z3.object({
|
|
|
487
509
|
})
|
|
488
510
|
).nonempty()
|
|
489
511
|
});
|
|
512
|
+
var CreateCliLoginZ = z3.object({
|
|
513
|
+
insert_cli_login_one: z3.object({
|
|
514
|
+
id: z3.string()
|
|
515
|
+
})
|
|
516
|
+
});
|
|
517
|
+
var GetEncryptedApiTokenZ = z3.object({
|
|
518
|
+
cli_login_by_pk: z3.object({
|
|
519
|
+
encryptedApiToken: z3.string().nullable()
|
|
520
|
+
})
|
|
521
|
+
});
|
|
490
522
|
|
|
491
523
|
// src/features/analysis/graphql/gql.ts
|
|
492
524
|
var debug5 = Debug5("mobbdev:gql");
|
|
493
525
|
var GQLClient = class {
|
|
494
526
|
constructor(args) {
|
|
495
|
-
const {
|
|
496
|
-
debug5(`init with apiKey ${apiKey}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
};
|
|
500
|
-
this._client = new GraphQLClient(API_URL, { headers });
|
|
527
|
+
const { apiKey } = args;
|
|
528
|
+
debug5(`init with apiKey ${apiKey}`);
|
|
529
|
+
this._client = new GraphQLClient(API_URL, {
|
|
530
|
+
headers: { "x-mobb-key": apiKey || "" }
|
|
531
|
+
});
|
|
501
532
|
}
|
|
502
533
|
async getUserInfo() {
|
|
503
534
|
const { me } = await this._client.request(ME);
|
|
504
535
|
return me;
|
|
505
536
|
}
|
|
537
|
+
async createCliLogin(variables) {
|
|
538
|
+
const res = CreateCliLoginZ.parse(
|
|
539
|
+
await this._client.request(
|
|
540
|
+
CREATE_CLI_LOGIN,
|
|
541
|
+
variables
|
|
542
|
+
)
|
|
543
|
+
);
|
|
544
|
+
return res.insert_cli_login_one.id;
|
|
545
|
+
}
|
|
506
546
|
async verifyToken() {
|
|
507
547
|
await this.createCommunityUser();
|
|
508
548
|
try {
|
|
@@ -526,6 +566,13 @@ var GQLClient = class {
|
|
|
526
566
|
projectId: org.projects[0].id
|
|
527
567
|
};
|
|
528
568
|
}
|
|
569
|
+
async getEncryptedApiToken(variables) {
|
|
570
|
+
const res = await this._client.request(
|
|
571
|
+
GET_ENCRYPTED_API_TOKEN,
|
|
572
|
+
variables
|
|
573
|
+
);
|
|
574
|
+
return GetEncryptedApiTokenZ.parse(res).cli_login_by_pk.encryptedApiToken;
|
|
575
|
+
}
|
|
529
576
|
async createCommunityUser() {
|
|
530
577
|
try {
|
|
531
578
|
await this._client.request(CREATE_COMMUNITY_USER);
|
|
@@ -761,6 +808,8 @@ var { CliError: CliError2, Spinner: Spinner2, keypress: keypress2, getDirName: g
|
|
|
761
808
|
var webLoginUrl = `${WEB_APP_URL}/cli-login`;
|
|
762
809
|
var githubSubmitUrl = `${WEB_APP_URL}/gh-callback`;
|
|
763
810
|
var githubAuthUrl = `${WEB_APP_URL}/github-auth`;
|
|
811
|
+
var LOGIN_MAX_WAIT = 10 * 60 * 1e3;
|
|
812
|
+
var LOGIN_CHECK_DELAY = 5 * 1e3;
|
|
764
813
|
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, ${chalk3.bgBlue(
|
|
765
814
|
"press any key to continue"
|
|
766
815
|
)};`;
|
|
@@ -781,7 +830,7 @@ if (!semver.satisfies(process.version, packageJson.engines.node)) {
|
|
|
781
830
|
`${packageJson.name} requires node version ${packageJson.engines.node}, but running ${process.version}.`
|
|
782
831
|
);
|
|
783
832
|
}
|
|
784
|
-
var config2 = new Configstore(packageJson.name, {
|
|
833
|
+
var config2 = new Configstore(packageJson.name, { apiToken: "" });
|
|
785
834
|
debug9("config %o", config2);
|
|
786
835
|
async function runAnalysis(params, options) {
|
|
787
836
|
try {
|
|
@@ -809,10 +858,9 @@ async function _scan({
|
|
|
809
858
|
debug9("start %s %s", dirname, repo);
|
|
810
859
|
const { createSpinner: createSpinner3 } = Spinner2({ ci });
|
|
811
860
|
skipPrompts = skipPrompts || ci;
|
|
812
|
-
let
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
let gqlClient = new GQLClient(apiKey ? { apiKey } : { token });
|
|
861
|
+
let gqlClient = new GQLClient({
|
|
862
|
+
apiKey: apiKey || config2.get("apiToken")
|
|
863
|
+
});
|
|
816
864
|
await handleMobbLogin();
|
|
817
865
|
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId();
|
|
818
866
|
const {
|
|
@@ -836,8 +884,8 @@ async function _scan({
|
|
|
836
884
|
`Cannot access repo ${repo} with the provided token, please visit ${githubAuthUrl} to refresh your Github token`
|
|
837
885
|
);
|
|
838
886
|
}
|
|
839
|
-
const { token
|
|
840
|
-
githubToken =
|
|
887
|
+
const { token } = await handleGithubIntegration();
|
|
888
|
+
githubToken = token;
|
|
841
889
|
}
|
|
842
890
|
const reference = ref ?? (await getRepo(repo, { token: githubToken })).data.default_branch;
|
|
843
891
|
debug9("org id %s", organizationId);
|
|
@@ -907,41 +955,67 @@ async function _scan({
|
|
|
907
955
|
);
|
|
908
956
|
}
|
|
909
957
|
async function handleMobbLogin() {
|
|
910
|
-
if (
|
|
958
|
+
if (await gqlClient.verifyToken()) {
|
|
911
959
|
createSpinner3().start().success({
|
|
912
960
|
text: "\u{1F513} Logged in to Mobb successfully"
|
|
913
961
|
});
|
|
914
962
|
return;
|
|
915
|
-
}
|
|
916
|
-
if (apiKey && !await gqlClient.verifyToken()) {
|
|
963
|
+
} else if (apiKey) {
|
|
917
964
|
createSpinner3().start().error({
|
|
918
965
|
text: "\u{1F513} Logged in to Mobb failed - check your api-key"
|
|
919
966
|
});
|
|
920
967
|
throw new CliError2();
|
|
921
968
|
}
|
|
922
|
-
const
|
|
969
|
+
const loginSpinner = createSpinner3().start();
|
|
923
970
|
if (!skipPrompts) {
|
|
924
|
-
|
|
971
|
+
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
925
972
|
await keypress2();
|
|
926
973
|
}
|
|
927
|
-
|
|
974
|
+
loginSpinner.update({
|
|
928
975
|
text: "\u{1F513} Waiting for Mobb login..."
|
|
929
976
|
});
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
977
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
|
|
978
|
+
modulusLength: 2048
|
|
979
|
+
});
|
|
980
|
+
const loginId = await gqlClient.createCliLogin({
|
|
981
|
+
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
933
982
|
});
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
983
|
+
const browserUrl = `${webLoginUrl}/${loginId}`;
|
|
984
|
+
!ci && console.log(
|
|
985
|
+
`If the page does not open automatically, kindly access it through ${browserUrl}.`
|
|
986
|
+
);
|
|
987
|
+
await open3(browserUrl);
|
|
988
|
+
let newApiToken = null;
|
|
989
|
+
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
990
|
+
const encryptedApiToken = await gqlClient.getEncryptedApiToken({
|
|
991
|
+
loginId
|
|
992
|
+
});
|
|
993
|
+
loginSpinner.spin();
|
|
994
|
+
if (encryptedApiToken) {
|
|
995
|
+
debug9("encrypted API token received %s", encryptedApiToken);
|
|
996
|
+
newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
997
|
+
debug9("API token decrypted");
|
|
998
|
+
break;
|
|
999
|
+
}
|
|
1000
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
1001
|
+
}
|
|
1002
|
+
if (!newApiToken) {
|
|
1003
|
+
loginSpinner.error({
|
|
1004
|
+
text: "Login timeout error"
|
|
1005
|
+
});
|
|
1006
|
+
throw new CliError2();
|
|
1007
|
+
}
|
|
1008
|
+
gqlClient = new GQLClient({ apiKey: newApiToken });
|
|
1009
|
+
if (await gqlClient.verifyToken()) {
|
|
1010
|
+
debug9("set api token %s", newApiToken);
|
|
1011
|
+
config2.set("apiToken", newApiToken);
|
|
1012
|
+
loginSpinner.success({ text: "\u{1F513} Login to Mobb successful!" });
|
|
1013
|
+
} else {
|
|
1014
|
+
loginSpinner.error({
|
|
938
1015
|
text: "Something went wrong, API token is invalid."
|
|
939
1016
|
});
|
|
940
1017
|
throw new CliError2();
|
|
941
1018
|
}
|
|
942
|
-
debug9("set token %s", token);
|
|
943
|
-
config2.set("token", token);
|
|
944
|
-
mobbLoginSpinner.success({ text: "\u{1F513} Login to Mobb successful!" });
|
|
945
1019
|
}
|
|
946
1020
|
async function handleGithubIntegration() {
|
|
947
1021
|
const addGithubIntegration = skipPrompts ? true : await githubIntegrationPrompt();
|
|
@@ -976,7 +1050,7 @@ async function _scan({
|
|
|
976
1050
|
uploadKey: reportUploadInfo.uploadKey
|
|
977
1051
|
});
|
|
978
1052
|
} catch (e) {
|
|
979
|
-
uploadReportSpinner2.error({ text: "\u{1F4C1}
|
|
1053
|
+
uploadReportSpinner2.error({ text: "\u{1F4C1} Report upload failed" });
|
|
980
1054
|
throw e;
|
|
981
1055
|
}
|
|
982
1056
|
uploadReportSpinner2.success({
|
|
@@ -991,7 +1065,7 @@ async function _scan({
|
|
|
991
1065
|
uploadKey: repoUploadInfo.uploadKey
|
|
992
1066
|
});
|
|
993
1067
|
} catch (e) {
|
|
994
|
-
uploadRepoSpinner.error({ text: "\u{1F4C1}
|
|
1068
|
+
uploadRepoSpinner.error({ text: "\u{1F4C1} Repo upload failed" });
|
|
995
1069
|
throw e;
|
|
996
1070
|
}
|
|
997
1071
|
uploadRepoSpinner.success({ text: "\u{1F4C1} Uploading Repo successful!" });
|
|
@@ -1081,6 +1155,15 @@ var ciOption = {
|
|
|
1081
1155
|
type: "boolean",
|
|
1082
1156
|
default: false
|
|
1083
1157
|
};
|
|
1158
|
+
var apiKeyOption = {
|
|
1159
|
+
type: "string",
|
|
1160
|
+
describe: chalk4.bold("Mobb authentication api-key")
|
|
1161
|
+
};
|
|
1162
|
+
var commitHashOption = {
|
|
1163
|
+
alias: "ch",
|
|
1164
|
+
describe: chalk4.bold("Hash of the commit"),
|
|
1165
|
+
type: "string"
|
|
1166
|
+
};
|
|
1084
1167
|
|
|
1085
1168
|
// src/args/validation.ts
|
|
1086
1169
|
import chalk5 from "chalk";
|
|
@@ -1157,7 +1240,7 @@ function analyzeBuilder(yargs2) {
|
|
|
1157
1240
|
alias: "commit-hash",
|
|
1158
1241
|
describe: chalk6.bold("Hash of the commit"),
|
|
1159
1242
|
type: "string"
|
|
1160
|
-
}).option("y", yesOption).option("ci", ciOption).example(
|
|
1243
|
+
}).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).example(
|
|
1161
1244
|
"$0 analyze -r https://github.com/WebGoat/WebGoat -f <your_vulirabitliy_report_path>",
|
|
1162
1245
|
"analyze an existing repository"
|
|
1163
1246
|
).help();
|
|
@@ -1190,7 +1273,7 @@ function scanBuilder(args) {
|
|
|
1190
1273
|
alias: "scanner",
|
|
1191
1274
|
choices: Object.values(SCANNERS),
|
|
1192
1275
|
describe: chalk7.bold("Select the scanner to use")
|
|
1193
|
-
}).option("y", yesOption).option("ci", ciOption).example(
|
|
1276
|
+
}).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).example(
|
|
1194
1277
|
"$0 scan -r https://github.com/WebGoat/WebGoat",
|
|
1195
1278
|
"Scan an existing repository"
|
|
1196
1279
|
).help();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobbdev",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Automated secure code remediation tool",
|
|
5
5
|
"repository": "https://github.com/mobb-dev/bugsy",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"lint": "eslint --cache --max-warnings 0 --ignore-path .eslintignore --ext .ts,.tsx,.jsx .",
|
|
14
14
|
"lint:fix": "eslint --fix --cache --max-warnings 0 --ignore-path .eslintignore --ext .js,.ts,.tsx,.jsx .",
|
|
15
15
|
"lint:fix:files": "eslint --fix --cache --max-warnings 0 --ignore-path .eslintignore --ext .js,.ts,.tsx,.jsx",
|
|
16
|
-
"prepack": "
|
|
16
|
+
"prepack": "dotenv-vault pull production .env && pnpm build"
|
|
17
17
|
},
|
|
18
18
|
"bin": {
|
|
19
19
|
"mobbdev": "bin/cli.mjs"
|