mobbdev 1.4.21 → 1.4.23
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/args/commands/upload_ai_blame.mjs +133 -38
- package/dist/index.mjs +613 -354
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -417,6 +417,7 @@ var init_client_generates = __esm({
|
|
|
417
417
|
return Vulnerability_Report_Issue_State_Enum2;
|
|
418
418
|
})(Vulnerability_Report_Issue_State_Enum || {});
|
|
419
419
|
Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Tag_Enum3) => {
|
|
420
|
+
Vulnerability_Report_Issue_Tag_Enum3["AgenticRemediationInProgress"] = "AGENTIC_REMEDIATION_IN_PROGRESS";
|
|
420
421
|
Vulnerability_Report_Issue_Tag_Enum3["AutogeneratedCode"] = "AUTOGENERATED_CODE";
|
|
421
422
|
Vulnerability_Report_Issue_Tag_Enum3["AuxiliaryCode"] = "AUXILIARY_CODE";
|
|
422
423
|
Vulnerability_Report_Issue_Tag_Enum3["FalsePositive"] = "FALSE_POSITIVE";
|
|
@@ -1592,7 +1593,8 @@ var init_getIssueType = __esm({
|
|
|
1592
1593
|
["TEST_CODE" /* TestCode */]: "The flagged code resides in a test-specific path or context. This categorization indicates that **it supports testing scenarios and is isolated from production use**.",
|
|
1593
1594
|
["UNFIXABLE" /* Unfixable */]: "The flagged code cannot be fixed",
|
|
1594
1595
|
["VENDOR_CODE" /* VendorCode */]: "The flagged code originates from a third-party library or dependency maintained externally. This categorization suggests that **the issue lies outside the application's direct control** and should be addressed by the vendor if necessary.",
|
|
1595
|
-
["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report."
|
|
1596
|
+
["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report.",
|
|
1597
|
+
["AGENTIC_REMEDIATION_IN_PROGRESS" /* AgenticRemediationInProgress */]: "Mobb is currently retrying remediation on this issue. The state will refresh automatically once the run finishes."
|
|
1596
1598
|
};
|
|
1597
1599
|
}
|
|
1598
1600
|
});
|
|
@@ -3872,9 +3874,9 @@ var init_GitService = __esm({
|
|
|
3872
3874
|
this.log("[GitService] Git repository validation successful", "debug");
|
|
3873
3875
|
return { isValid: true };
|
|
3874
3876
|
} catch (error) {
|
|
3875
|
-
const
|
|
3876
|
-
this.log(`[GitService] ${
|
|
3877
|
-
return { isValid: false, error:
|
|
3877
|
+
const errorMessage3 = `Failed to verify git repository: ${error.message}`;
|
|
3878
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3879
|
+
return { isValid: false, error: errorMessage3 };
|
|
3878
3880
|
}
|
|
3879
3881
|
}
|
|
3880
3882
|
/**
|
|
@@ -3920,9 +3922,9 @@ var init_GitService = __esm({
|
|
|
3920
3922
|
});
|
|
3921
3923
|
return { files, deletedFiles, status };
|
|
3922
3924
|
} catch (error) {
|
|
3923
|
-
const
|
|
3924
|
-
this.log(`[GitService] ${
|
|
3925
|
-
throw new Error(
|
|
3925
|
+
const errorMessage3 = `Failed to get git status: ${error.message}`;
|
|
3926
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3927
|
+
throw new Error(errorMessage3);
|
|
3926
3928
|
}
|
|
3927
3929
|
}
|
|
3928
3930
|
/**
|
|
@@ -3948,9 +3950,9 @@ var init_GitService = __esm({
|
|
|
3948
3950
|
reference
|
|
3949
3951
|
};
|
|
3950
3952
|
} catch (error) {
|
|
3951
|
-
const
|
|
3952
|
-
this.log(`[GitService] ${
|
|
3953
|
-
throw new Error(
|
|
3953
|
+
const errorMessage3 = `Failed to get git repository information: ${error.message}`;
|
|
3954
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3955
|
+
throw new Error(errorMessage3);
|
|
3954
3956
|
}
|
|
3955
3957
|
}
|
|
3956
3958
|
/**
|
|
@@ -3988,9 +3990,9 @@ var init_GitService = __esm({
|
|
|
3988
3990
|
this.log("[GitService] Current branch retrieved", "debug", { branch });
|
|
3989
3991
|
return branch;
|
|
3990
3992
|
} catch (error) {
|
|
3991
|
-
const
|
|
3992
|
-
this.log(`[GitService] ${
|
|
3993
|
-
throw new Error(
|
|
3993
|
+
const errorMessage3 = `Failed to get current branch: ${error.message}`;
|
|
3994
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3995
|
+
throw new Error(errorMessage3);
|
|
3994
3996
|
}
|
|
3995
3997
|
}
|
|
3996
3998
|
/**
|
|
@@ -4003,9 +4005,9 @@ var init_GitService = __esm({
|
|
|
4003
4005
|
this.log("[GitService] Current commit hash retrieved", "debug", { hash });
|
|
4004
4006
|
return hash;
|
|
4005
4007
|
} catch (error) {
|
|
4006
|
-
const
|
|
4007
|
-
this.log(`[GitService] ${
|
|
4008
|
-
throw new Error(
|
|
4008
|
+
const errorMessage3 = `Failed to get current commit hash: ${error.message}`;
|
|
4009
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4010
|
+
throw new Error(errorMessage3);
|
|
4009
4011
|
}
|
|
4010
4012
|
}
|
|
4011
4013
|
/**
|
|
@@ -4053,8 +4055,8 @@ var init_GitService = __esm({
|
|
|
4053
4055
|
);
|
|
4054
4056
|
return { hash, branch };
|
|
4055
4057
|
} catch (error) {
|
|
4056
|
-
const
|
|
4057
|
-
this.log(`[GitService] ${
|
|
4058
|
+
const errorMessage3 = `Failed to get current commit hash and branch: ${error.message}`;
|
|
4059
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4058
4060
|
return { hash: "", branch: "" };
|
|
4059
4061
|
}
|
|
4060
4062
|
}
|
|
@@ -4072,9 +4074,9 @@ var init_GitService = __esm({
|
|
|
4072
4074
|
});
|
|
4073
4075
|
return normalizedUrl;
|
|
4074
4076
|
} catch (error) {
|
|
4075
|
-
const
|
|
4076
|
-
this.log(`[GitService] ${
|
|
4077
|
-
throw new Error(
|
|
4077
|
+
const errorMessage3 = `Failed to get remote repository URL: ${error.message}`;
|
|
4078
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4079
|
+
throw new Error(errorMessage3);
|
|
4078
4080
|
}
|
|
4079
4081
|
}
|
|
4080
4082
|
/**
|
|
@@ -4195,9 +4197,9 @@ var init_GitService = __esm({
|
|
|
4195
4197
|
commitCount: commitsProcessed
|
|
4196
4198
|
};
|
|
4197
4199
|
} catch (error) {
|
|
4198
|
-
const
|
|
4199
|
-
this.log(`[GitService] ${
|
|
4200
|
-
throw new Error(
|
|
4200
|
+
const errorMessage3 = `Failed to get recently changed files: ${error.message}`;
|
|
4201
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4202
|
+
throw new Error(errorMessage3);
|
|
4201
4203
|
}
|
|
4202
4204
|
}
|
|
4203
4205
|
/**
|
|
@@ -4241,8 +4243,8 @@ ${rootContent}`;
|
|
|
4241
4243
|
);
|
|
4242
4244
|
return combinedContent.trimEnd();
|
|
4243
4245
|
} catch (error) {
|
|
4244
|
-
const
|
|
4245
|
-
this.log(`[GitService] ${
|
|
4246
|
+
const errorMessage3 = `Failed to get .gitignore contents: ${error.message}`;
|
|
4247
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4246
4248
|
return null;
|
|
4247
4249
|
}
|
|
4248
4250
|
}
|
|
@@ -4262,9 +4264,9 @@ ${rootContent}`;
|
|
|
4262
4264
|
this.log("[GitService] Git root retrieved", "debug", { gitRoot });
|
|
4263
4265
|
return gitRoot;
|
|
4264
4266
|
} catch (error) {
|
|
4265
|
-
const
|
|
4266
|
-
this.log(`[GitService] ${
|
|
4267
|
-
throw new Error(
|
|
4267
|
+
const errorMessage3 = `Failed to get git repository root: ${error.message}`;
|
|
4268
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4269
|
+
throw new Error(errorMessage3);
|
|
4268
4270
|
}
|
|
4269
4271
|
}
|
|
4270
4272
|
/**
|
|
@@ -4303,9 +4305,9 @@ ${rootContent}`;
|
|
|
4303
4305
|
});
|
|
4304
4306
|
return true;
|
|
4305
4307
|
} catch (error) {
|
|
4306
|
-
const
|
|
4307
|
-
this.log(`[GitService] ${
|
|
4308
|
-
throw new Error(
|
|
4308
|
+
const errorMessage3 = `Failed to ensure .gitignore entry: ${error.message}`;
|
|
4309
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error, entry });
|
|
4310
|
+
throw new Error(errorMessage3);
|
|
4309
4311
|
}
|
|
4310
4312
|
}
|
|
4311
4313
|
/**
|
|
@@ -4323,9 +4325,9 @@ ${rootContent}`;
|
|
|
4323
4325
|
});
|
|
4324
4326
|
return exists2;
|
|
4325
4327
|
} catch (error) {
|
|
4326
|
-
const
|
|
4327
|
-
this.log(`[GitService] ${
|
|
4328
|
-
throw new Error(
|
|
4328
|
+
const errorMessage3 = `Failed to check .gitignore existence: ${error.message}`;
|
|
4329
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4330
|
+
throw new Error(errorMessage3);
|
|
4329
4331
|
}
|
|
4330
4332
|
}
|
|
4331
4333
|
/**
|
|
@@ -4385,8 +4387,8 @@ ${rootContent}`;
|
|
|
4385
4387
|
coAuthors: parsed.coAuthors
|
|
4386
4388
|
};
|
|
4387
4389
|
} catch (error) {
|
|
4388
|
-
const
|
|
4389
|
-
this.log(`[GitService] ${
|
|
4390
|
+
const errorMessage3 = `Failed to get local commit data: ${error.message}`;
|
|
4391
|
+
this.log(`[GitService] ${errorMessage3}`, "debug", { error, commitSha });
|
|
4390
4392
|
return null;
|
|
4391
4393
|
}
|
|
4392
4394
|
}
|
|
@@ -4395,7 +4397,7 @@ ${rootContent}`;
|
|
|
4395
4397
|
});
|
|
4396
4398
|
|
|
4397
4399
|
// src/index.ts
|
|
4398
|
-
import
|
|
4400
|
+
import Debug23 from "debug";
|
|
4399
4401
|
import { hideBin } from "yargs/helpers";
|
|
4400
4402
|
|
|
4401
4403
|
// src/args/yargs.ts
|
|
@@ -5231,6 +5233,48 @@ var languages = {
|
|
|
5231
5233
|
init_client_generates();
|
|
5232
5234
|
import { z as z4 } from "zod";
|
|
5233
5235
|
|
|
5236
|
+
// src/features/analysis/scm/shared/src/storedQuestionData/cpp/index.ts
|
|
5237
|
+
init_client_generates();
|
|
5238
|
+
|
|
5239
|
+
// src/features/analysis/scm/shared/src/storedQuestionData/cpp/commandInjection.ts
|
|
5240
|
+
var commandInjection = {
|
|
5241
|
+
isUnixShellCommandPart: {
|
|
5242
|
+
content: () => "Is the input data interpolated into a shell command (not the program name or shell structure)?",
|
|
5243
|
+
description: () => `\`system()\` / \`popen()\` hand the whole string to \`/bin/sh -c\`. Answer **yes** when the input is *data* placed into a fixed command, for example:
|
|
5244
|
+
|
|
5245
|
+
- \`sprintf(cmd, "grep %s file.txt", input); system(cmd);\`
|
|
5246
|
+
- \`sprintf(cmd, "ping -c 5 %s", input); system(cmd);\`
|
|
5247
|
+
|
|
5248
|
+
Answer **no** (the input is not plain data) when the input is:
|
|
5249
|
+
|
|
5250
|
+
1. The program/executable itself:
|
|
5251
|
+
- \`system(input);\`
|
|
5252
|
+
- \`sprintf(cmd, "%s -x", input);\`
|
|
5253
|
+
2. A command after a pipe or redirect:
|
|
5254
|
+
- \`sprintf(cmd, "cat file.txt | %s", input);\`
|
|
5255
|
+
3. A part of a non-Unix or cross-platform shell command.
|
|
5256
|
+
4. A part of embedded code in another language:
|
|
5257
|
+
- \`sprintf(cmd, "php -r \\"echo '%s';\\"", input);\`
|
|
5258
|
+
- \`sprintf(cmd, "awk '%s' file", input);\`
|
|
5259
|
+
5. A flag/option that controls a tool's behaviour:
|
|
5260
|
+
- \`sprintf(cmd, "git --upload-pack %s", input);\``,
|
|
5261
|
+
guidance: () => "If yes and the command can run without a shell, it is rewritten to a no-shell argument-vector call (`posix_spawn`); if it needs the shell, the tainted argument is escaped in place so the shell keeps working. If the answer is no (the input controls the program or shell structure), there is no safe automatic rewrite, so the fix is withheld and the sink is left for manual review."
|
|
5262
|
+
},
|
|
5263
|
+
executableLocationPath: {
|
|
5264
|
+
content: () => "What is the absolute path of the directory containing the executable?",
|
|
5265
|
+
description: () => `When \`system()\` is rewritten to an \`execv()\` argument-vector call, the program is run by its path with **no \`$PATH\` search**, so a relative program name (e.g. \`tail\`) cannot be resolved and a poisoned \`PATH\` cannot be used to run a look-alike binary.
|
|
5266
|
+
|
|
5267
|
+
Provide the absolute directory that contains the executable (e.g. \`/usr/bin\`); the fix prepends it to the bare program name to form an absolute path.`,
|
|
5268
|
+
guidance: () => "Only asked when the program name in the command has no `/`. A program that is already an absolute or relative path (contains `/`) is used as written."
|
|
5269
|
+
}
|
|
5270
|
+
};
|
|
5271
|
+
|
|
5272
|
+
// src/features/analysis/scm/shared/src/storedQuestionData/cpp/index.ts
|
|
5273
|
+
var vulnerabilities11 = {
|
|
5274
|
+
["CMDi" /* CmDi */]: commandInjection
|
|
5275
|
+
};
|
|
5276
|
+
var cpp_default = vulnerabilities11;
|
|
5277
|
+
|
|
5234
5278
|
// src/features/analysis/scm/shared/src/storedQuestionData/csharp/index.ts
|
|
5235
5279
|
init_client_generates();
|
|
5236
5280
|
|
|
@@ -5527,7 +5571,7 @@ var xxe = {
|
|
|
5527
5571
|
};
|
|
5528
5572
|
|
|
5529
5573
|
// src/features/analysis/scm/shared/src/storedQuestionData/csharp/index.ts
|
|
5530
|
-
var
|
|
5574
|
+
var vulnerabilities12 = {
|
|
5531
5575
|
["LOG_FORGING" /* LogForging */]: logForging,
|
|
5532
5576
|
["SSRF" /* Ssrf */]: ssrf2,
|
|
5533
5577
|
["XXE" /* Xxe */]: xxe,
|
|
@@ -5548,7 +5592,7 @@ var vulnerabilities11 = {
|
|
|
5548
5592
|
["SQL_Injection" /* SqlInjection */]: sqlInjection2,
|
|
5549
5593
|
["REQUEST_PARAMETERS_BOUND_VIA_INPUT" /* RequestParametersBoundViaInput */]: requestParametersBoundViaInput
|
|
5550
5594
|
};
|
|
5551
|
-
var csharp_default2 =
|
|
5595
|
+
var csharp_default2 = vulnerabilities12;
|
|
5552
5596
|
|
|
5553
5597
|
// src/features/analysis/scm/shared/src/storedQuestionData/go/index.ts
|
|
5554
5598
|
init_client_generates();
|
|
@@ -5581,18 +5625,18 @@ var websocketMissingOriginCheck = {
|
|
|
5581
5625
|
};
|
|
5582
5626
|
|
|
5583
5627
|
// src/features/analysis/scm/shared/src/storedQuestionData/go/index.ts
|
|
5584
|
-
var
|
|
5628
|
+
var vulnerabilities13 = {
|
|
5585
5629
|
["LOG_FORGING" /* LogForging */]: logForging2,
|
|
5586
5630
|
["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: missingSslMinversion,
|
|
5587
5631
|
["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: websocketMissingOriginCheck
|
|
5588
5632
|
};
|
|
5589
|
-
var go_default2 =
|
|
5633
|
+
var go_default2 = vulnerabilities13;
|
|
5590
5634
|
|
|
5591
5635
|
// src/features/analysis/scm/shared/src/storedQuestionData/java/index.ts
|
|
5592
5636
|
init_client_generates();
|
|
5593
5637
|
|
|
5594
5638
|
// src/features/analysis/scm/shared/src/storedQuestionData/java/commandInjection.ts
|
|
5595
|
-
var
|
|
5639
|
+
var commandInjection2 = {
|
|
5596
5640
|
isUnixShellCommandPart: {
|
|
5597
5641
|
content: () => "Is the input part of Unix shell command?",
|
|
5598
5642
|
description: () => `For example:
|
|
@@ -6046,10 +6090,10 @@ var xxe2 = {
|
|
|
6046
6090
|
};
|
|
6047
6091
|
|
|
6048
6092
|
// src/features/analysis/scm/shared/src/storedQuestionData/java/index.ts
|
|
6049
|
-
var
|
|
6093
|
+
var vulnerabilities14 = {
|
|
6050
6094
|
["SQL_Injection" /* SqlInjection */]: sqlInjection3,
|
|
6051
6095
|
["CMDi_relative_path_command" /* CmDiRelativePathCommand */]: relativePathCommand,
|
|
6052
|
-
["CMDi" /* CmDi */]:
|
|
6096
|
+
["CMDi" /* CmDi */]: commandInjection2,
|
|
6053
6097
|
["CONFUSING_NAMING" /* ConfusingNaming */]: confusingNaming,
|
|
6054
6098
|
["ERROR_CONDTION_WITHOUT_ACTION" /* ErrorCondtionWithoutAction */]: errorConditionWithoutAction,
|
|
6055
6099
|
["XXE" /* Xxe */]: xxe2,
|
|
@@ -6074,7 +6118,7 @@ var vulnerabilities13 = {
|
|
|
6074
6118
|
["ERRONEOUS_STRING_COMPARE" /* ErroneousStringCompare */]: erroneousStringCompare,
|
|
6075
6119
|
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: duplicatedStrings
|
|
6076
6120
|
};
|
|
6077
|
-
var java_default2 =
|
|
6121
|
+
var java_default2 = vulnerabilities14;
|
|
6078
6122
|
|
|
6079
6123
|
// src/features/analysis/scm/shared/src/storedQuestionData/js/index.ts
|
|
6080
6124
|
init_client_generates();
|
|
@@ -6089,7 +6133,7 @@ var csrf2 = {
|
|
|
6089
6133
|
};
|
|
6090
6134
|
|
|
6091
6135
|
// src/features/analysis/scm/shared/src/storedQuestionData/js/commandInjection.ts
|
|
6092
|
-
var
|
|
6136
|
+
var commandInjection3 = {
|
|
6093
6137
|
isCommandExecutable: {
|
|
6094
6138
|
content: () => "Commands can be intrinsically unsafe if they call out to other executables or run arbitary code",
|
|
6095
6139
|
description: () => `Does the command fall into one of the following categories:
|
|
@@ -6403,8 +6447,8 @@ var xss3 = {
|
|
|
6403
6447
|
};
|
|
6404
6448
|
|
|
6405
6449
|
// src/features/analysis/scm/shared/src/storedQuestionData/js/index.ts
|
|
6406
|
-
var
|
|
6407
|
-
["CMDi" /* CmDi */]:
|
|
6450
|
+
var vulnerabilities15 = {
|
|
6451
|
+
["CMDi" /* CmDi */]: commandInjection3,
|
|
6408
6452
|
["GRAPHQL_DEPTH_LIMIT" /* GraphqlDepthLimit */]: graphqlDepthLimit,
|
|
6409
6453
|
["INSECURE_RANDOMNESS" /* InsecureRandomness */]: insecureRandomness2,
|
|
6410
6454
|
["SSRF" /* Ssrf */]: ssrf4,
|
|
@@ -6426,7 +6470,7 @@ var vulnerabilities14 = {
|
|
|
6426
6470
|
["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: hardcodedDomainInHtml,
|
|
6427
6471
|
["CSRF" /* Csrf */]: csrf2
|
|
6428
6472
|
};
|
|
6429
|
-
var js_default =
|
|
6473
|
+
var js_default = vulnerabilities15;
|
|
6430
6474
|
|
|
6431
6475
|
// src/features/analysis/scm/shared/src/storedQuestionData/python/index.ts
|
|
6432
6476
|
init_client_generates();
|
|
@@ -6500,7 +6544,7 @@ var uncheckedLoopCondition3 = {
|
|
|
6500
6544
|
};
|
|
6501
6545
|
|
|
6502
6546
|
// src/features/analysis/scm/shared/src/storedQuestionData/python/index.ts
|
|
6503
|
-
var
|
|
6547
|
+
var vulnerabilities16 = {
|
|
6504
6548
|
["CSRF" /* Csrf */]: csrf2,
|
|
6505
6549
|
["LOG_FORGING" /* LogForging */]: logForging5,
|
|
6506
6550
|
["OPEN_REDIRECT" /* OpenRedirect */]: openRedirect3,
|
|
@@ -6509,7 +6553,7 @@ var vulnerabilities15 = {
|
|
|
6509
6553
|
["MISSING_ENCODING_FILE_OPEN" /* MissingEncodingFileOpen */]: missingEncoding,
|
|
6510
6554
|
["SSRF" /* Ssrf */]: ssrf5
|
|
6511
6555
|
};
|
|
6512
|
-
var python_default2 =
|
|
6556
|
+
var python_default2 = vulnerabilities16;
|
|
6513
6557
|
|
|
6514
6558
|
// src/features/analysis/scm/shared/src/storedQuestionData/xml/index.ts
|
|
6515
6559
|
init_client_generates();
|
|
@@ -6526,10 +6570,10 @@ A value too high will cause performance issues up to and including denial of ser
|
|
|
6526
6570
|
};
|
|
6527
6571
|
|
|
6528
6572
|
// src/features/analysis/scm/shared/src/storedQuestionData/xml/index.ts
|
|
6529
|
-
var
|
|
6573
|
+
var vulnerabilities17 = {
|
|
6530
6574
|
["WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */]: unboundedOccurrences
|
|
6531
6575
|
};
|
|
6532
|
-
var xml_default2 =
|
|
6576
|
+
var xml_default2 = vulnerabilities17;
|
|
6533
6577
|
|
|
6534
6578
|
// src/features/analysis/scm/shared/src/storedQuestionData/yaml/index.ts
|
|
6535
6579
|
init_client_generates();
|
|
@@ -6562,12 +6606,12 @@ var writableFilesystemService = {
|
|
|
6562
6606
|
};
|
|
6563
6607
|
|
|
6564
6608
|
// src/features/analysis/scm/shared/src/storedQuestionData/yaml/index.ts
|
|
6565
|
-
var
|
|
6609
|
+
var vulnerabilities18 = {
|
|
6566
6610
|
["PORT_ALL_INTERFACES" /* PortAllInterfaces */]: portAllInterfaces,
|
|
6567
6611
|
["WRITABLE_FILESYSTEM_SERVICE" /* WritableFilesystemService */]: writableFilesystemService,
|
|
6568
6612
|
["NO_NEW_PRIVILEGES" /* NoNewPrivileges */]: noNewPrivileges
|
|
6569
6613
|
};
|
|
6570
|
-
var yaml_default =
|
|
6614
|
+
var yaml_default = vulnerabilities18;
|
|
6571
6615
|
|
|
6572
6616
|
// src/features/analysis/scm/shared/src/storedQuestionData/index.ts
|
|
6573
6617
|
var StoredQuestionDataItemZ = z4.object({
|
|
@@ -6582,6 +6626,7 @@ var languages2 = {
|
|
|
6582
6626
|
["CSharp" /* CSharp */]: csharp_default2,
|
|
6583
6627
|
["Python" /* Python */]: python_default2,
|
|
6584
6628
|
["Go" /* Go */]: go_default2,
|
|
6629
|
+
["Cpp" /* Cpp */]: cpp_default,
|
|
6585
6630
|
["YAML" /* Yaml */]: yaml_default
|
|
6586
6631
|
};
|
|
6587
6632
|
var storedQuestionData_default = languages2;
|
|
@@ -9325,8 +9370,8 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9325
9370
|
(Number.parseInt(headers["x-ratelimit-reset"], 10) * 1e3 - Date.now()) / 1e3
|
|
9326
9371
|
)
|
|
9327
9372
|
) : void 0;
|
|
9328
|
-
const
|
|
9329
|
-
if (status === 403 && retryAfter !== void 0 ||
|
|
9373
|
+
const errorMessage3 = errorObj.message || (error instanceof Error ? error.message : String(error));
|
|
9374
|
+
if (status === 403 && retryAfter !== void 0 || errorMessage3.toLowerCase().includes("rate limit") || errorMessage3.toLowerCase().includes("api rate limit exceeded")) {
|
|
9330
9375
|
throw new RateLimitError(
|
|
9331
9376
|
"GitHub API rate limit exceeded",
|
|
9332
9377
|
scmType,
|
|
@@ -9354,7 +9399,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9354
9399
|
const errorCode = errorObj.code || errorObj.response?.code;
|
|
9355
9400
|
if (errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ENOTFOUND" || errorCode === "EAI_AGAIN") {
|
|
9356
9401
|
throw new NetworkError(
|
|
9357
|
-
`GitHub network error: ${
|
|
9402
|
+
`GitHub network error: ${errorMessage3}`,
|
|
9358
9403
|
scmType,
|
|
9359
9404
|
errorCode
|
|
9360
9405
|
);
|
|
@@ -9362,7 +9407,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9362
9407
|
if (error instanceof RateLimitError || error instanceof InvalidAccessTokenError || error instanceof ScmBadCredentialsError || error instanceof InvalidRepoUrlError || error instanceof NetworkError || error instanceof InvalidUrlPatternError) {
|
|
9363
9408
|
throw error;
|
|
9364
9409
|
}
|
|
9365
|
-
throw new Error(`GitHub API error: ${
|
|
9410
|
+
throw new Error(`GitHub API error: ${errorMessage3}`);
|
|
9366
9411
|
}
|
|
9367
9412
|
async function githubValidateParams(url, accessToken) {
|
|
9368
9413
|
try {
|
|
@@ -9596,48 +9641,65 @@ function getGithubSdk(params = {}) {
|
|
|
9596
9641
|
return false;
|
|
9597
9642
|
}
|
|
9598
9643
|
},
|
|
9599
|
-
async
|
|
9644
|
+
async listAuthenticatedUserReposPage(params2) {
|
|
9645
|
+
const {
|
|
9646
|
+
sort = { field: "updated", order: "desc" },
|
|
9647
|
+
perPage = 10,
|
|
9648
|
+
page = 1
|
|
9649
|
+
} = params2;
|
|
9650
|
+
const githubSort = sort.field === "name" ? "full_name" : sort.field === "created" ? "created" : "updated";
|
|
9600
9651
|
try {
|
|
9601
|
-
const
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
});
|
|
9620
|
-
}
|
|
9621
|
-
hasMore = githubRepos.data.length >= perPage;
|
|
9622
|
-
page++;
|
|
9623
|
-
}
|
|
9624
|
-
return allRepos;
|
|
9652
|
+
const githubRepos = await octokit.request(GET_USER_REPOS, {
|
|
9653
|
+
sort: githubSort,
|
|
9654
|
+
direction: sort.order,
|
|
9655
|
+
per_page: perPage,
|
|
9656
|
+
page
|
|
9657
|
+
});
|
|
9658
|
+
const items = githubRepos.data.map((repo) => ({
|
|
9659
|
+
repoName: repo.name,
|
|
9660
|
+
repoUrl: repo.html_url,
|
|
9661
|
+
repoOwner: repo.owner.login,
|
|
9662
|
+
repoLanguages: repo.language ? [repo.language] : [],
|
|
9663
|
+
repoIsPublic: !repo.private,
|
|
9664
|
+
repoUpdatedAt: repo.updated_at
|
|
9665
|
+
}));
|
|
9666
|
+
return {
|
|
9667
|
+
items,
|
|
9668
|
+
hasMore: githubRepos.data.length >= perPage
|
|
9669
|
+
};
|
|
9625
9670
|
} catch (e) {
|
|
9626
9671
|
if (e instanceof RequestError && e.status === 401) {
|
|
9627
9672
|
console.warn(
|
|
9628
9673
|
"GitHub API returned 401 Unauthorized when listing repos - token may be expired or lack repo scope"
|
|
9629
9674
|
);
|
|
9630
|
-
return [];
|
|
9675
|
+
return { items: [], hasMore: false };
|
|
9631
9676
|
}
|
|
9632
9677
|
if (e instanceof RequestError && e.status === 404) {
|
|
9633
9678
|
console.warn(
|
|
9634
9679
|
"GitHub API returned 404 Not Found when listing repos - user may not exist"
|
|
9635
9680
|
);
|
|
9636
|
-
return [];
|
|
9681
|
+
return { items: [], hasMore: false };
|
|
9637
9682
|
}
|
|
9638
9683
|
throw e;
|
|
9639
9684
|
}
|
|
9640
9685
|
},
|
|
9686
|
+
async getGithubRepoList() {
|
|
9687
|
+
const allRepos = [];
|
|
9688
|
+
let page = 1;
|
|
9689
|
+
const perPage = 100;
|
|
9690
|
+
let hasMore = true;
|
|
9691
|
+
while (hasMore) {
|
|
9692
|
+
const pageResult = await this.listAuthenticatedUserReposPage({
|
|
9693
|
+
sort: { field: "updated", order: "desc" },
|
|
9694
|
+
perPage,
|
|
9695
|
+
page
|
|
9696
|
+
});
|
|
9697
|
+
allRepos.push(...pageResult.items);
|
|
9698
|
+
hasMore = pageResult.hasMore;
|
|
9699
|
+
page++;
|
|
9700
|
+
}
|
|
9701
|
+
return allRepos;
|
|
9702
|
+
},
|
|
9641
9703
|
async getGithubRepoDefaultBranch(repoUrl) {
|
|
9642
9704
|
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
9643
9705
|
const repos = await octokit.rest.repos.get({ repo, owner });
|
|
@@ -10697,23 +10759,25 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
10697
10759
|
});
|
|
10698
10760
|
}
|
|
10699
10761
|
/**
|
|
10700
|
-
* Override searchRepos
|
|
10701
|
-
*
|
|
10702
|
-
*
|
|
10703
|
-
*
|
|
10704
|
-
* is requested, we fall back to fetching all repos and sorting in-memory.
|
|
10762
|
+
* Override searchRepos for efficient server-side pagination.
|
|
10763
|
+
* - With scmOrg: GitHub Search API (`org:…`)
|
|
10764
|
+
* - Without scmOrg: paginated `GET /user/repos`
|
|
10765
|
+
* - Name sort: in-memory over full list
|
|
10705
10766
|
*/
|
|
10706
10767
|
async searchRepos(params) {
|
|
10707
10768
|
this._validateAccessToken();
|
|
10708
10769
|
const sort = params.sort || { field: "updated", order: "desc" };
|
|
10709
|
-
if (
|
|
10770
|
+
if (sort.field === "name") {
|
|
10710
10771
|
return this.searchReposInMemory(params);
|
|
10711
10772
|
}
|
|
10773
|
+
if (!params.scmOrg) {
|
|
10774
|
+
return this.searchReposWithUserReposApi(params);
|
|
10775
|
+
}
|
|
10712
10776
|
return this.searchReposWithApi(params);
|
|
10713
10777
|
}
|
|
10714
10778
|
/**
|
|
10715
10779
|
* Search repos by fetching all and sorting/paginating in-memory.
|
|
10716
|
-
* Used when name sorting is requested
|
|
10780
|
+
* Used only when name sorting is requested.
|
|
10717
10781
|
*/
|
|
10718
10782
|
async searchReposInMemory(params) {
|
|
10719
10783
|
const repos = await this.getRepoList(params.scmOrg);
|
|
@@ -10741,6 +10805,24 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
10741
10805
|
hasMore: nextOffset < sortedRepos.length
|
|
10742
10806
|
};
|
|
10743
10807
|
}
|
|
10808
|
+
/**
|
|
10809
|
+
* Paginated repo list for authenticated user when no GitHub org is configured.
|
|
10810
|
+
*/
|
|
10811
|
+
async searchReposWithUserReposApi(params) {
|
|
10812
|
+
const page = parseCursorSafe(params.cursor, 1);
|
|
10813
|
+
const perPage = params.limit || 10;
|
|
10814
|
+
const sort = params.sort || { field: "updated", order: "desc" };
|
|
10815
|
+
const pageResult = await this.githubSdk.listAuthenticatedUserReposPage({
|
|
10816
|
+
sort,
|
|
10817
|
+
perPage,
|
|
10818
|
+
page
|
|
10819
|
+
});
|
|
10820
|
+
return {
|
|
10821
|
+
results: pageResult.items,
|
|
10822
|
+
nextCursor: pageResult.hasMore ? String(page + 1) : void 0,
|
|
10823
|
+
hasMore: pageResult.hasMore
|
|
10824
|
+
};
|
|
10825
|
+
}
|
|
10744
10826
|
/**
|
|
10745
10827
|
* Search repos using GitHub Search API for efficient server-side pagination.
|
|
10746
10828
|
* Only supports date-based sorting (updated/created).
|
|
@@ -13112,7 +13194,7 @@ import path10 from "path";
|
|
|
13112
13194
|
import { env as env2 } from "process";
|
|
13113
13195
|
import { pipeline } from "stream/promises";
|
|
13114
13196
|
import chalk7 from "chalk";
|
|
13115
|
-
import
|
|
13197
|
+
import Debug22 from "debug";
|
|
13116
13198
|
import extract from "extract-zip";
|
|
13117
13199
|
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
13118
13200
|
import fetch4 from "node-fetch";
|
|
@@ -13123,7 +13205,7 @@ import { z as z31 } from "zod";
|
|
|
13123
13205
|
// src/commands/AuthManager.ts
|
|
13124
13206
|
import crypto from "crypto";
|
|
13125
13207
|
import os3 from "os";
|
|
13126
|
-
import
|
|
13208
|
+
import Debug11 from "debug";
|
|
13127
13209
|
import open from "open";
|
|
13128
13210
|
|
|
13129
13211
|
// src/features/analysis/graphql/gql.ts
|
|
@@ -13778,11 +13860,11 @@ var GQLClient = class {
|
|
|
13778
13860
|
{
|
|
13779
13861
|
next: async (data) => {
|
|
13780
13862
|
if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
|
|
13781
|
-
const
|
|
13863
|
+
const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
|
|
13782
13864
|
subscription.unsubscribe();
|
|
13783
13865
|
reject(
|
|
13784
13866
|
new ReportDigestError(
|
|
13785
|
-
|
|
13867
|
+
errorMessage3,
|
|
13786
13868
|
data.analysis?.failReason ?? ""
|
|
13787
13869
|
)
|
|
13788
13870
|
);
|
|
@@ -13846,9 +13928,9 @@ var GQLClient = class {
|
|
|
13846
13928
|
`[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
|
|
13847
13929
|
);
|
|
13848
13930
|
if (!analysis.state || analysis.state === "Failed" /* Failed */) {
|
|
13849
|
-
const
|
|
13850
|
-
debug7(`[pollForAnalysisState] Analysis failed: ${
|
|
13851
|
-
throw new ReportDigestError(
|
|
13931
|
+
const errorMessage3 = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
|
|
13932
|
+
debug7(`[pollForAnalysisState] Analysis failed: ${errorMessage3}`);
|
|
13933
|
+
throw new ReportDigestError(errorMessage3, analysis.failReason ?? "");
|
|
13852
13934
|
}
|
|
13853
13935
|
if (callbackStates.includes(analysis.state)) {
|
|
13854
13936
|
debug7(
|
|
@@ -13949,7 +14031,7 @@ var GQLClient = class {
|
|
|
13949
14031
|
};
|
|
13950
14032
|
|
|
13951
14033
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
13952
|
-
import
|
|
14034
|
+
import Debug10 from "debug";
|
|
13953
14035
|
|
|
13954
14036
|
// src/args/commands/upload_ai_blame.ts
|
|
13955
14037
|
import fsPromises2 from "fs/promises";
|
|
@@ -14068,12 +14150,28 @@ init_urlParser2();
|
|
|
14068
14150
|
import Debug8 from "debug";
|
|
14069
14151
|
import fetch3, { File, fileFrom, FormData } from "node-fetch";
|
|
14070
14152
|
var debug9 = Debug8("mobbdev:upload-file");
|
|
14153
|
+
var S3UploadError = class extends Error {
|
|
14154
|
+
constructor(status, s3Code, s3Message) {
|
|
14155
|
+
super(`Failed to upload the file: ${status}`);
|
|
14156
|
+
this.status = status;
|
|
14157
|
+
this.s3Code = s3Code;
|
|
14158
|
+
this.s3Message = s3Message;
|
|
14159
|
+
this.name = "S3UploadError";
|
|
14160
|
+
}
|
|
14161
|
+
};
|
|
14162
|
+
function parseS3ErrorBody(body) {
|
|
14163
|
+
return {
|
|
14164
|
+
code: body.match(/<Code>([^<]+)<\/Code>/)?.[1],
|
|
14165
|
+
message: body.match(/<Message>([^<]+)<\/Message>/)?.[1]
|
|
14166
|
+
};
|
|
14167
|
+
}
|
|
14071
14168
|
async function uploadFile({
|
|
14072
14169
|
file,
|
|
14073
14170
|
url,
|
|
14074
14171
|
uploadKey,
|
|
14075
14172
|
uploadFields,
|
|
14076
|
-
logger: logger3
|
|
14173
|
+
logger: logger3,
|
|
14174
|
+
signal
|
|
14077
14175
|
}) {
|
|
14078
14176
|
const logInfo2 = logger3 || ((_message, _data) => {
|
|
14079
14177
|
});
|
|
@@ -14095,18 +14193,44 @@ async function uploadFile({
|
|
|
14095
14193
|
} else {
|
|
14096
14194
|
debug9("upload file from buffer");
|
|
14097
14195
|
logInfo2(`FileUpload: upload file from buffer`);
|
|
14098
|
-
form.append(
|
|
14196
|
+
form.append(
|
|
14197
|
+
"file",
|
|
14198
|
+
new File(
|
|
14199
|
+
[
|
|
14200
|
+
new Uint8Array(
|
|
14201
|
+
file.buffer,
|
|
14202
|
+
file.byteOffset,
|
|
14203
|
+
file.byteLength
|
|
14204
|
+
)
|
|
14205
|
+
],
|
|
14206
|
+
"file"
|
|
14207
|
+
)
|
|
14208
|
+
);
|
|
14099
14209
|
}
|
|
14100
14210
|
const agent = getProxyAgent(url);
|
|
14101
14211
|
const response = await fetch3(url, {
|
|
14102
14212
|
method: "POST",
|
|
14103
14213
|
body: form,
|
|
14104
|
-
agent
|
|
14214
|
+
agent,
|
|
14215
|
+
signal
|
|
14105
14216
|
});
|
|
14106
14217
|
if (!response.ok) {
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14218
|
+
let bodyText = "";
|
|
14219
|
+
try {
|
|
14220
|
+
bodyText = await response.text();
|
|
14221
|
+
} catch {
|
|
14222
|
+
}
|
|
14223
|
+
const { code, message } = parseS3ErrorBody(bodyText);
|
|
14224
|
+
debug9(
|
|
14225
|
+
"error from S3 status=%d code=%s message=%s",
|
|
14226
|
+
response.status,
|
|
14227
|
+
code,
|
|
14228
|
+
message
|
|
14229
|
+
);
|
|
14230
|
+
logInfo2(
|
|
14231
|
+
`FileUpload: error from S3 status=${response.status} code=${code ?? "unknown"}`
|
|
14232
|
+
);
|
|
14233
|
+
throw new S3UploadError(response.status, code, message);
|
|
14110
14234
|
}
|
|
14111
14235
|
debug9("upload file done");
|
|
14112
14236
|
logInfo2(`FileUpload: upload file done`);
|
|
@@ -14772,39 +14896,240 @@ function withTimeout(promise, ms, label) {
|
|
|
14772
14896
|
]);
|
|
14773
14897
|
}
|
|
14774
14898
|
|
|
14899
|
+
// src/features/analysis/graphql/s3-raw-data-upload.ts
|
|
14900
|
+
import { setTimeout as sleep2 } from "timers/promises";
|
|
14901
|
+
import Debug9 from "debug";
|
|
14902
|
+
var debug10 = Debug9("mobbdev:tracy-s3-upload");
|
|
14903
|
+
var S3_OP_TIMEOUT_MS = 3e4;
|
|
14904
|
+
var MAX_TOTAL_S3_UPLOAD_MS = 12e4;
|
|
14905
|
+
var MAX_CONCURRENT_S3_UPLOADS = 5;
|
|
14906
|
+
var URL_REFRESH_MS = 20 * 60 * 1e3;
|
|
14907
|
+
var MAX_UPLOAD_ATTEMPTS = 3;
|
|
14908
|
+
var RETRY_BACKOFF_MS = 500;
|
|
14909
|
+
var MAX_S3_MESSAGE_CHARS = 120;
|
|
14910
|
+
var errorMessage = (e) => e instanceof Error ? e.message : String(e);
|
|
14911
|
+
function classifyUploadError(reason) {
|
|
14912
|
+
if (reason instanceof S3UploadError) {
|
|
14913
|
+
return {
|
|
14914
|
+
status: reason.status,
|
|
14915
|
+
s3Code: reason.s3Code,
|
|
14916
|
+
s3Message: reason.s3Message,
|
|
14917
|
+
retryable: reason.status !== 400 && reason.status !== 401
|
|
14918
|
+
};
|
|
14919
|
+
}
|
|
14920
|
+
return { retryable: true };
|
|
14921
|
+
}
|
|
14922
|
+
function createPresignedUrlProvider(client) {
|
|
14923
|
+
let creds = null;
|
|
14924
|
+
let fetchedAt = 0;
|
|
14925
|
+
const fetchFresh = async () => {
|
|
14926
|
+
let res;
|
|
14927
|
+
try {
|
|
14928
|
+
res = await withTimeout(
|
|
14929
|
+
client.getTracyRawDataUploadUrl(),
|
|
14930
|
+
S3_OP_TIMEOUT_MS,
|
|
14931
|
+
"[step:s3-url] getTracyRawDataUploadUrl"
|
|
14932
|
+
);
|
|
14933
|
+
} catch (err) {
|
|
14934
|
+
throw new Error(
|
|
14935
|
+
`[step:s3-url] Failed to fetch S3 upload URL: ${errorMessage(err)}`
|
|
14936
|
+
);
|
|
14937
|
+
}
|
|
14938
|
+
const { url, uploadFieldsJSON, keyPrefix } = res.getTracyRawDataUploadUrl;
|
|
14939
|
+
if (!url || !uploadFieldsJSON || !keyPrefix) {
|
|
14940
|
+
throw new Error(
|
|
14941
|
+
`[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
|
|
14942
|
+
);
|
|
14943
|
+
}
|
|
14944
|
+
try {
|
|
14945
|
+
return { url, uploadFields: JSON.parse(uploadFieldsJSON), keyPrefix };
|
|
14946
|
+
} catch {
|
|
14947
|
+
throw new Error("[step:s3-url] Malformed uploadFieldsJSON from server");
|
|
14948
|
+
}
|
|
14949
|
+
};
|
|
14950
|
+
const refresh = async () => {
|
|
14951
|
+
creds = await fetchFresh();
|
|
14952
|
+
fetchedAt = Date.now();
|
|
14953
|
+
return creds;
|
|
14954
|
+
};
|
|
14955
|
+
return {
|
|
14956
|
+
refresh,
|
|
14957
|
+
/** Cached creds, refreshed if missing or near expiry. */
|
|
14958
|
+
async current() {
|
|
14959
|
+
if (!creds || Date.now() - fetchedAt > URL_REFRESH_MS) return refresh();
|
|
14960
|
+
return creds;
|
|
14961
|
+
}
|
|
14962
|
+
};
|
|
14963
|
+
}
|
|
14964
|
+
async function uploadRawDataToS3(client, entries, serializedByIndex) {
|
|
14965
|
+
const uploaded = /* @__PURE__ */ new Map();
|
|
14966
|
+
const urls = createPresignedUrlProvider(client);
|
|
14967
|
+
debug10(
|
|
14968
|
+
"[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
|
|
14969
|
+
entries.length,
|
|
14970
|
+
MAX_CONCURRENT_S3_UPLOADS
|
|
14971
|
+
);
|
|
14972
|
+
const start = Date.now();
|
|
14973
|
+
const deadline = start + MAX_TOTAL_S3_UPLOAD_MS;
|
|
14974
|
+
const uploadPass = async (pass) => {
|
|
14975
|
+
const failures = [];
|
|
14976
|
+
for (let i = 0; i < pass.length; i += MAX_CONCURRENT_S3_UPLOADS) {
|
|
14977
|
+
if (Date.now() > deadline) {
|
|
14978
|
+
for (const entry of pass.slice(i)) {
|
|
14979
|
+
failures.push({
|
|
14980
|
+
entry,
|
|
14981
|
+
kind: { retryable: false },
|
|
14982
|
+
message: `[step:s3-upload] aborted: exceeded ${MAX_TOTAL_S3_UPLOAD_MS}ms total upload budget`
|
|
14983
|
+
});
|
|
14984
|
+
}
|
|
14985
|
+
break;
|
|
14986
|
+
}
|
|
14987
|
+
const { url, uploadFields, keyPrefix } = await urls.current();
|
|
14988
|
+
const chunk = pass.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
|
|
14989
|
+
const settled = await Promise.allSettled(
|
|
14990
|
+
chunk.map(async (entry) => {
|
|
14991
|
+
const rawDataJson = serializedByIndex.get(entry.index);
|
|
14992
|
+
if (!rawDataJson) {
|
|
14993
|
+
debug10("No serialized rawData for recordId=%s", entry.recordId);
|
|
14994
|
+
return;
|
|
14995
|
+
}
|
|
14996
|
+
const uploadKey = `${keyPrefix}${entry.recordId}.json`;
|
|
14997
|
+
const signal = AbortSignal.timeout(S3_OP_TIMEOUT_MS);
|
|
14998
|
+
try {
|
|
14999
|
+
await uploadFile({
|
|
15000
|
+
file: Buffer.from(rawDataJson, "utf-8"),
|
|
15001
|
+
url,
|
|
15002
|
+
uploadKey,
|
|
15003
|
+
uploadFields,
|
|
15004
|
+
signal
|
|
15005
|
+
});
|
|
15006
|
+
} catch (err) {
|
|
15007
|
+
if (signal.aborted) {
|
|
15008
|
+
throw new Error(
|
|
15009
|
+
`[step:s3-upload] uploadFile ${entry.recordId} timed out after ${S3_OP_TIMEOUT_MS}ms`
|
|
15010
|
+
);
|
|
15011
|
+
}
|
|
15012
|
+
throw err;
|
|
15013
|
+
}
|
|
15014
|
+
uploaded.set(entry.index, uploadKey);
|
|
15015
|
+
serializedByIndex.delete(entry.index);
|
|
15016
|
+
})
|
|
15017
|
+
);
|
|
15018
|
+
settled.forEach((outcome, idx) => {
|
|
15019
|
+
if (outcome.status === "rejected") {
|
|
15020
|
+
failures.push({
|
|
15021
|
+
entry: chunk[idx],
|
|
15022
|
+
kind: classifyUploadError(outcome.reason),
|
|
15023
|
+
message: errorMessage(outcome.reason)
|
|
15024
|
+
});
|
|
15025
|
+
}
|
|
15026
|
+
});
|
|
15027
|
+
}
|
|
15028
|
+
return failures;
|
|
15029
|
+
};
|
|
15030
|
+
const failuresByRecord = /* @__PURE__ */ new Map();
|
|
15031
|
+
try {
|
|
15032
|
+
await urls.refresh();
|
|
15033
|
+
let pending = entries;
|
|
15034
|
+
for (let attempt = 1; attempt <= MAX_UPLOAD_ATTEMPTS; attempt++) {
|
|
15035
|
+
const failures = await uploadPass(pending);
|
|
15036
|
+
for (const entry of pending) failuresByRecord.delete(entry.recordId);
|
|
15037
|
+
for (const failure of failures)
|
|
15038
|
+
failuresByRecord.set(failure.entry.recordId, failure);
|
|
15039
|
+
const retryable = failures.filter((failure) => failure.kind.retryable);
|
|
15040
|
+
if (retryable.length === 0 || attempt === MAX_UPLOAD_ATTEMPTS || Date.now() > deadline) {
|
|
15041
|
+
break;
|
|
15042
|
+
}
|
|
15043
|
+
debug10(
|
|
15044
|
+
"[step:s3-upload] attempt %d failed for %d record(s); refreshing URL and retrying",
|
|
15045
|
+
attempt,
|
|
15046
|
+
retryable.length
|
|
15047
|
+
);
|
|
15048
|
+
await sleep2(RETRY_BACKOFF_MS * attempt);
|
|
15049
|
+
await urls.refresh();
|
|
15050
|
+
pending = retryable.map((failure) => failure.entry);
|
|
15051
|
+
}
|
|
15052
|
+
} catch (err) {
|
|
15053
|
+
return { uploaded, errors: [errorMessage(err)] };
|
|
15054
|
+
}
|
|
15055
|
+
debug10("[perf] s3-upload %d files: %dms", entries.length, Date.now() - start);
|
|
15056
|
+
const missing = entries.filter((entry) => !uploaded.has(entry.index));
|
|
15057
|
+
if (missing.length === 0) {
|
|
15058
|
+
debug10("[step:s3-upload] S3 uploads complete");
|
|
15059
|
+
return { uploaded, errors: null };
|
|
15060
|
+
}
|
|
15061
|
+
const detail = missing.map((entry) => {
|
|
15062
|
+
const failure = failuresByRecord.get(entry.recordId);
|
|
15063
|
+
const code = failure?.kind.s3Code ? ` ${failure.kind.s3Code}` : "";
|
|
15064
|
+
const message = failure?.kind.s3Message ? ` "${failure.kind.s3Message.slice(0, MAX_S3_MESSAGE_CHARS)}"` : "";
|
|
15065
|
+
return `[step:s3-upload] ${entry.recordId}: HTTP ${failure?.kind.status ?? "n/a"}${code}${message} (${failure?.message ?? "unknown"})`;
|
|
15066
|
+
});
|
|
15067
|
+
debug10(
|
|
15068
|
+
"[step:s3-upload] Records missing S3 keys: %O",
|
|
15069
|
+
missing.map((entry) => entry.recordId)
|
|
15070
|
+
);
|
|
15071
|
+
return {
|
|
15072
|
+
uploaded,
|
|
15073
|
+
errors: [
|
|
15074
|
+
`[step:s3-upload] Failed to upload rawData for ${missing.length} record(s): ${missing.map((entry) => entry.recordId).join(", ")}`,
|
|
15075
|
+
...detail
|
|
15076
|
+
]
|
|
15077
|
+
};
|
|
15078
|
+
}
|
|
15079
|
+
|
|
14775
15080
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
14776
|
-
var
|
|
15081
|
+
var debug11 = Debug10("mobbdev:tracy-batch-upload");
|
|
15082
|
+
var errorMessage2 = (e) => e instanceof Error ? e.message : String(e);
|
|
14777
15083
|
function timedStep(label, fn) {
|
|
14778
15084
|
const start = Date.now();
|
|
14779
15085
|
const result = fn();
|
|
14780
15086
|
const maybePromise = result instanceof Promise ? result : Promise.resolve(result);
|
|
14781
15087
|
return maybePromise.then(
|
|
14782
15088
|
(val) => {
|
|
14783
|
-
|
|
15089
|
+
debug11("[perf] %s: %dms", label, Date.now() - start);
|
|
14784
15090
|
return val;
|
|
14785
15091
|
},
|
|
14786
15092
|
(err) => {
|
|
14787
|
-
|
|
15093
|
+
debug11("[perf] %s FAILED: %dms", label, Date.now() - start);
|
|
14788
15094
|
throw err;
|
|
14789
15095
|
}
|
|
14790
15096
|
);
|
|
14791
15097
|
}
|
|
14792
15098
|
var BATCH_TIMEOUT_MS = 3e4;
|
|
15099
|
+
var MIN_RAWDATA_BYTES = 5;
|
|
15100
|
+
var MAX_DEGENERATE_SAMPLE_CHARS = 500;
|
|
15101
|
+
var REDACTED_SAMPLE = "<redacted: sanitization disabled>";
|
|
15102
|
+
var MAX_DEGENERATE_LOG_RECORDS = 20;
|
|
15103
|
+
var DEGENERATE_RECORDS_LOG_MESSAGE = "Skipped empty/degenerate rawData records before S3 upload";
|
|
15104
|
+
function degenerateRecordsLogFields(degenerate) {
|
|
15105
|
+
return {
|
|
15106
|
+
count: degenerate.length,
|
|
15107
|
+
records: degenerate.slice(0, MAX_DEGENERATE_LOG_RECORDS)
|
|
15108
|
+
};
|
|
15109
|
+
}
|
|
15110
|
+
function isStructurallyEmptyPayload(serialized) {
|
|
15111
|
+
const trimmed = serialized.trim();
|
|
15112
|
+
if (trimmed === "" || trimmed === "null" || trimmed === '""') return true;
|
|
15113
|
+
const isObject = trimmed.startsWith("{") && trimmed.endsWith("}");
|
|
15114
|
+
const isArray = trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
15115
|
+
if (isObject || isArray) return trimmed.slice(1, -1).trim() === "";
|
|
15116
|
+
return false;
|
|
15117
|
+
}
|
|
14793
15118
|
async function sanitizeRawData(rawData) {
|
|
14794
15119
|
const start = Date.now();
|
|
14795
15120
|
try {
|
|
14796
15121
|
const sanitized = await sanitizeData(rawData);
|
|
14797
15122
|
const serialized = JSON.stringify(sanitized);
|
|
14798
|
-
|
|
15123
|
+
debug11(
|
|
14799
15124
|
"[perf] sanitizeRawData: %dms (%d bytes)",
|
|
14800
15125
|
Date.now() - start,
|
|
14801
15126
|
serialized.length
|
|
14802
15127
|
);
|
|
14803
15128
|
return serialized;
|
|
14804
15129
|
} catch (err) {
|
|
14805
|
-
|
|
14806
|
-
"[tracy] sanitizeRawData failed, falling back to unsanitized:",
|
|
14807
|
-
err
|
|
15130
|
+
debug11(
|
|
15131
|
+
"[tracy] sanitizeRawData failed, falling back to unsanitized: %s",
|
|
15132
|
+
errorMessage2(err)
|
|
14808
15133
|
);
|
|
14809
15134
|
return JSON.stringify(rawData);
|
|
14810
15135
|
}
|
|
@@ -14814,12 +15139,13 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14814
15139
|
const defaultClientVersion = packageJson.version;
|
|
14815
15140
|
const shouldSanitize = options?.sanitize ?? true;
|
|
14816
15141
|
const defaults = workingDir != null ? await readRepoState(workingDir) : { repositoryUrl: null, branch: null, commitSha: null };
|
|
14817
|
-
|
|
15142
|
+
debug11(
|
|
14818
15143
|
"[step:sanitize] %s %d records",
|
|
14819
15144
|
shouldSanitize ? "Sanitizing" : "Serializing",
|
|
14820
15145
|
rawRecords.length
|
|
14821
15146
|
);
|
|
14822
15147
|
const serializedRawDataByIndex = /* @__PURE__ */ new Map();
|
|
15148
|
+
const degenerate = [];
|
|
14823
15149
|
const records = await timedStep(
|
|
14824
15150
|
`${shouldSanitize ? "sanitize" : "serialize"} ${rawRecords.length} records`,
|
|
14825
15151
|
async () => {
|
|
@@ -14828,7 +15154,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14828
15154
|
const record = rawRecords[index];
|
|
14829
15155
|
if (record.rawData != null && record.rawDataS3Key == null) {
|
|
14830
15156
|
const serialized = shouldSanitize ? await sanitizeRawData(record.rawData) : JSON.stringify(record.rawData);
|
|
14831
|
-
|
|
15157
|
+
const bytes = Buffer.byteLength(serialized, "utf-8");
|
|
15158
|
+
if (bytes < MIN_RAWDATA_BYTES || isStructurallyEmptyPayload(serialized)) {
|
|
15159
|
+
degenerate.push({
|
|
15160
|
+
recordId: record.recordId,
|
|
15161
|
+
platform: record.platform,
|
|
15162
|
+
filePath: record.filePath,
|
|
15163
|
+
editType: record.editType,
|
|
15164
|
+
bytes,
|
|
15165
|
+
sample: shouldSanitize ? serialized.slice(0, MAX_DEGENERATE_SAMPLE_CHARS) : REDACTED_SAMPLE
|
|
15166
|
+
});
|
|
15167
|
+
} else {
|
|
15168
|
+
serializedRawDataByIndex.set(index, serialized);
|
|
15169
|
+
}
|
|
14832
15170
|
}
|
|
14833
15171
|
const { rawData: _rawData, ...rest } = record;
|
|
14834
15172
|
results.push({
|
|
@@ -14844,104 +15182,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14844
15182
|
return results;
|
|
14845
15183
|
}
|
|
14846
15184
|
);
|
|
14847
|
-
const
|
|
15185
|
+
const degenerateOut = degenerate.length > 0 ? degenerate : void 0;
|
|
15186
|
+
const finish = (result) => ({ ...result, degenerate: degenerateOut });
|
|
15187
|
+
const recordsWithRawData = rawRecords.map((record, index) => ({ recordId: record.recordId, index })).filter((entry) => serializedRawDataByIndex.has(entry.index));
|
|
14848
15188
|
if (recordsWithRawData.length > 0) {
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
recordsWithRawData
|
|
14852
|
-
|
|
14853
|
-
let uploadUrlResult;
|
|
14854
|
-
try {
|
|
14855
|
-
uploadUrlResult = await withTimeout(
|
|
14856
|
-
client.getTracyRawDataUploadUrl(),
|
|
14857
|
-
BATCH_TIMEOUT_MS,
|
|
14858
|
-
"[step:s3-url] getTracyRawDataUploadUrl"
|
|
14859
|
-
);
|
|
14860
|
-
} catch (err) {
|
|
14861
|
-
return {
|
|
14862
|
-
ok: false,
|
|
14863
|
-
errors: [
|
|
14864
|
-
`[step:s3-url] Failed to fetch S3 upload URL: ${err.message}`
|
|
14865
|
-
]
|
|
14866
|
-
};
|
|
14867
|
-
}
|
|
14868
|
-
const { url, uploadFieldsJSON, keyPrefix } = uploadUrlResult.getTracyRawDataUploadUrl;
|
|
14869
|
-
if (!url || !uploadFieldsJSON || !keyPrefix) {
|
|
14870
|
-
return {
|
|
14871
|
-
ok: false,
|
|
14872
|
-
errors: [
|
|
14873
|
-
`[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
|
|
14874
|
-
]
|
|
14875
|
-
};
|
|
14876
|
-
}
|
|
14877
|
-
let uploadFields;
|
|
14878
|
-
try {
|
|
14879
|
-
uploadFields = JSON.parse(uploadFieldsJSON);
|
|
14880
|
-
} catch {
|
|
14881
|
-
return {
|
|
14882
|
-
ok: false,
|
|
14883
|
-
errors: ["[step:s3-url] Malformed uploadFieldsJSON from server"]
|
|
14884
|
-
};
|
|
14885
|
-
}
|
|
14886
|
-
const MAX_CONCURRENT_S3_UPLOADS = 5;
|
|
14887
|
-
debug10(
|
|
14888
|
-
"[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
|
|
14889
|
-
recordsWithRawData.length,
|
|
14890
|
-
MAX_CONCURRENT_S3_UPLOADS
|
|
15189
|
+
const { uploaded, errors } = await uploadRawDataToS3(
|
|
15190
|
+
client,
|
|
15191
|
+
recordsWithRawData,
|
|
15192
|
+
serializedRawDataByIndex
|
|
14891
15193
|
);
|
|
14892
|
-
const
|
|
14893
|
-
|
|
14894
|
-
for (let i = 0; i < recordsWithRawData.length; i += MAX_CONCURRENT_S3_UPLOADS) {
|
|
14895
|
-
const chunk = recordsWithRawData.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
|
|
14896
|
-
const chunkResults = await Promise.allSettled(
|
|
14897
|
-
chunk.map(async (entry) => {
|
|
14898
|
-
const rawDataJson = serializedRawDataByIndex.get(entry.index);
|
|
14899
|
-
if (!rawDataJson) {
|
|
14900
|
-
debug10("No serialized rawData for recordId=%s", entry.recordId);
|
|
14901
|
-
return;
|
|
14902
|
-
}
|
|
14903
|
-
const uploadKey = `${keyPrefix}${entry.recordId}.json`;
|
|
14904
|
-
await withTimeout(
|
|
14905
|
-
uploadFile({
|
|
14906
|
-
file: Buffer.from(rawDataJson, "utf-8"),
|
|
14907
|
-
url,
|
|
14908
|
-
uploadKey,
|
|
14909
|
-
uploadFields
|
|
14910
|
-
}),
|
|
14911
|
-
BATCH_TIMEOUT_MS,
|
|
14912
|
-
`[step:s3-upload] uploadFile ${entry.recordId}`
|
|
14913
|
-
);
|
|
14914
|
-
records[entry.index].rawDataS3Key = uploadKey;
|
|
14915
|
-
})
|
|
14916
|
-
);
|
|
14917
|
-
uploadResults.push(...chunkResults);
|
|
14918
|
-
}
|
|
14919
|
-
debug10(
|
|
14920
|
-
"[perf] s3-upload %d files: %dms",
|
|
14921
|
-
recordsWithRawData.length,
|
|
14922
|
-
Date.now() - s3Start
|
|
14923
|
-
);
|
|
14924
|
-
const uploadErrors = uploadResults.filter((r) => r.status === "rejected").map((r) => r.reason.message);
|
|
14925
|
-
if (uploadErrors.length > 0) {
|
|
14926
|
-
debug10("[step:s3-upload] S3 upload errors: %O", uploadErrors);
|
|
14927
|
-
}
|
|
14928
|
-
const missingS3Keys = recordsWithRawData.filter(
|
|
14929
|
-
(entry) => !records[entry.index].rawDataS3Key
|
|
14930
|
-
);
|
|
14931
|
-
if (missingS3Keys.length > 0) {
|
|
14932
|
-
const missingIds = missingS3Keys.map((e) => e.recordId);
|
|
14933
|
-
debug10("[step:s3-upload] Records missing S3 keys: %O", missingIds);
|
|
14934
|
-
return {
|
|
14935
|
-
ok: false,
|
|
14936
|
-
errors: [
|
|
14937
|
-
`[step:s3-upload] Failed to upload rawData for ${missingS3Keys.length} record(s): ${missingIds.join(", ")}`,
|
|
14938
|
-
...uploadErrors
|
|
14939
|
-
]
|
|
14940
|
-
};
|
|
14941
|
-
}
|
|
14942
|
-
debug10("[step:s3-upload] S3 uploads complete");
|
|
15194
|
+
for (const [index, key] of uploaded) records[index].rawDataS3Key = key;
|
|
15195
|
+
if (errors) return finish({ ok: false, errors });
|
|
14943
15196
|
}
|
|
14944
|
-
|
|
15197
|
+
debug11("[step:gql-submit] Submitting %d records via GraphQL", records.length);
|
|
14945
15198
|
try {
|
|
14946
15199
|
const result = await timedStep(
|
|
14947
15200
|
`gql-submit ${records.length} records`,
|
|
@@ -14952,21 +15205,21 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14952
15205
|
)
|
|
14953
15206
|
);
|
|
14954
15207
|
if (result.uploadTracyRecords.status !== "OK") {
|
|
14955
|
-
return {
|
|
15208
|
+
return finish({
|
|
14956
15209
|
ok: false,
|
|
14957
15210
|
errors: [
|
|
14958
15211
|
`[step:gql-submit] Server rejected: ${result.uploadTracyRecords.error ?? "Unknown server error"}`
|
|
14959
15212
|
]
|
|
14960
|
-
};
|
|
15213
|
+
});
|
|
14961
15214
|
}
|
|
14962
15215
|
} catch (err) {
|
|
14963
|
-
|
|
14964
|
-
return {
|
|
15216
|
+
debug11("[step:gql-submit] Upload failed: %s", errorMessage2(err));
|
|
15217
|
+
return finish({
|
|
14965
15218
|
ok: false,
|
|
14966
|
-
errors: [`[step:gql-submit] ${err
|
|
14967
|
-
};
|
|
15219
|
+
errors: [`[step:gql-submit] ${errorMessage2(err)}`]
|
|
15220
|
+
});
|
|
14968
15221
|
}
|
|
14969
|
-
return { ok: true, errors: null };
|
|
15222
|
+
return finish({ ok: true, errors: null });
|
|
14970
15223
|
}
|
|
14971
15224
|
|
|
14972
15225
|
// src/mcp/services/types.ts
|
|
@@ -15002,7 +15255,7 @@ function buildLoginUrl(baseUrl, loginId, hostname, context) {
|
|
|
15002
15255
|
}
|
|
15003
15256
|
|
|
15004
15257
|
// src/commands/AuthManager.ts
|
|
15005
|
-
var
|
|
15258
|
+
var debug12 = Debug11("mobbdev:auth");
|
|
15006
15259
|
var LOGIN_MAX_WAIT = 2 * 60 * 1e3;
|
|
15007
15260
|
var LOGIN_CHECK_DELAY = 2 * 1e3;
|
|
15008
15261
|
var _AuthManager = class _AuthManager {
|
|
@@ -15032,7 +15285,7 @@ var _AuthManager = class _AuthManager {
|
|
|
15032
15285
|
return false;
|
|
15033
15286
|
}
|
|
15034
15287
|
if (_AuthManager.browserCooldownMs > 0 && Date.now() - _AuthManager.lastBrowserOpenTime < _AuthManager.browserCooldownMs) {
|
|
15035
|
-
|
|
15288
|
+
debug12("browser cooldown active, skipping open");
|
|
15036
15289
|
return false;
|
|
15037
15290
|
}
|
|
15038
15291
|
open(this.currentBrowserUrl);
|
|
@@ -15085,7 +15338,7 @@ var _AuthManager = class _AuthManager {
|
|
|
15085
15338
|
const result = await this.checkAuthentication();
|
|
15086
15339
|
this.authenticated = result.isAuthenticated;
|
|
15087
15340
|
if (!result.isAuthenticated) {
|
|
15088
|
-
|
|
15341
|
+
debug12("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
|
|
15089
15342
|
}
|
|
15090
15343
|
}
|
|
15091
15344
|
return this.authenticated;
|
|
@@ -15173,9 +15426,9 @@ var _AuthManager = class _AuthManager {
|
|
|
15173
15426
|
return null;
|
|
15174
15427
|
} catch (error) {
|
|
15175
15428
|
if (isTransientError(error)) {
|
|
15176
|
-
|
|
15429
|
+
debug12("getApiToken: transient error, will retry");
|
|
15177
15430
|
} else {
|
|
15178
|
-
|
|
15431
|
+
debug12("getApiToken: unexpected error: %O", error);
|
|
15179
15432
|
}
|
|
15180
15433
|
return null;
|
|
15181
15434
|
}
|
|
@@ -15228,10 +15481,10 @@ __publicField(_AuthManager, "lastBrowserOpenTime", 0);
|
|
|
15228
15481
|
var AuthManager = _AuthManager;
|
|
15229
15482
|
|
|
15230
15483
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
15231
|
-
import
|
|
15484
|
+
import Debug15 from "debug";
|
|
15232
15485
|
|
|
15233
15486
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
15234
|
-
import
|
|
15487
|
+
import Debug14 from "debug";
|
|
15235
15488
|
import parseDiff from "parse-diff";
|
|
15236
15489
|
import { z as z29 } from "zod";
|
|
15237
15490
|
|
|
@@ -15243,9 +15496,9 @@ function keyBy(array, keyBy2) {
|
|
|
15243
15496
|
}
|
|
15244
15497
|
|
|
15245
15498
|
// src/features/analysis/utils/send_report.ts
|
|
15246
|
-
import
|
|
15499
|
+
import Debug12 from "debug";
|
|
15247
15500
|
init_client_generates();
|
|
15248
|
-
var
|
|
15501
|
+
var debug13 = Debug12("mobbdev:index");
|
|
15249
15502
|
async function sendReport({
|
|
15250
15503
|
spinner,
|
|
15251
15504
|
submitVulnerabilityReportVariables,
|
|
@@ -15257,7 +15510,7 @@ async function sendReport({
|
|
|
15257
15510
|
submitVulnerabilityReportVariables
|
|
15258
15511
|
);
|
|
15259
15512
|
if (submitRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
|
|
15260
|
-
|
|
15513
|
+
debug13("error submit vul report %s", submitRes);
|
|
15261
15514
|
throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
|
|
15262
15515
|
}
|
|
15263
15516
|
spinner.update({ text: progressMassages.processingVulnerabilityReport });
|
|
@@ -15269,7 +15522,7 @@ async function sendReport({
|
|
|
15269
15522
|
"Finished" /* Finished */
|
|
15270
15523
|
];
|
|
15271
15524
|
if (polling) {
|
|
15272
|
-
|
|
15525
|
+
debug13("[sendReport] Using POLLING mode for analysis state updates");
|
|
15273
15526
|
await gqlClient.pollForAnalysisState({
|
|
15274
15527
|
analysisId: submitRes.submitVulnerabilityReport.fixReportId,
|
|
15275
15528
|
callback,
|
|
@@ -15277,7 +15530,7 @@ async function sendReport({
|
|
|
15277
15530
|
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
15278
15531
|
});
|
|
15279
15532
|
} else {
|
|
15280
|
-
|
|
15533
|
+
debug13("[sendReport] Using WEBSOCKET mode for analysis state updates");
|
|
15281
15534
|
await gqlClient.subscribeToAnalysis({
|
|
15282
15535
|
subscribeToAnalysisParams: {
|
|
15283
15536
|
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
@@ -15321,10 +15574,10 @@ var scannerToFriendlyString = {
|
|
|
15321
15574
|
};
|
|
15322
15575
|
|
|
15323
15576
|
// src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
|
|
15324
|
-
import
|
|
15577
|
+
import Debug13 from "debug";
|
|
15325
15578
|
import { z as z28 } from "zod";
|
|
15326
15579
|
init_client_generates();
|
|
15327
|
-
var
|
|
15580
|
+
var debug14 = Debug13("mobbdev:handle-finished-analysis");
|
|
15328
15581
|
var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
|
|
15329
15582
|
function buildFixCommentBody({
|
|
15330
15583
|
fix,
|
|
@@ -15375,7 +15628,7 @@ function buildFixCommentBody({
|
|
|
15375
15628
|
safeIssueType: z28.nativeEnum(IssueType_Enum)
|
|
15376
15629
|
}).safeParse(fix);
|
|
15377
15630
|
if (!validFixParseRes.success) {
|
|
15378
|
-
|
|
15631
|
+
debug14(
|
|
15379
15632
|
`fix ${fixId} has custom issue type or language, therefore the commit description will not be added`,
|
|
15380
15633
|
validFixParseRes.error
|
|
15381
15634
|
);
|
|
@@ -15439,7 +15692,7 @@ ${issuePageLink}`;
|
|
|
15439
15692
|
}
|
|
15440
15693
|
|
|
15441
15694
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
15442
|
-
var
|
|
15695
|
+
var debug15 = Debug14("mobbdev:handle-finished-analysis");
|
|
15443
15696
|
function calculateRanges(integers) {
|
|
15444
15697
|
if (integers.length === 0) {
|
|
15445
15698
|
return [];
|
|
@@ -15473,7 +15726,7 @@ function deleteAllPreviousComments({
|
|
|
15473
15726
|
try {
|
|
15474
15727
|
return scm.deleteComment({ comment_id: comment.id });
|
|
15475
15728
|
} catch (e) {
|
|
15476
|
-
|
|
15729
|
+
debug15("delete comment failed %s", e);
|
|
15477
15730
|
return Promise.resolve();
|
|
15478
15731
|
}
|
|
15479
15732
|
});
|
|
@@ -15489,7 +15742,7 @@ function deleteAllPreviousGeneralPrComments(params) {
|
|
|
15489
15742
|
try {
|
|
15490
15743
|
return scm.deleteGeneralPrComment({ commentId: comment.id });
|
|
15491
15744
|
} catch (e) {
|
|
15492
|
-
|
|
15745
|
+
debug15("delete comment failed %s", e);
|
|
15493
15746
|
return Promise.resolve();
|
|
15494
15747
|
}
|
|
15495
15748
|
});
|
|
@@ -15633,7 +15886,7 @@ async function postAnalysisInsightComment(params) {
|
|
|
15633
15886
|
fixablePrVuls,
|
|
15634
15887
|
nonFixablePrVuls
|
|
15635
15888
|
} = prVulenrabilities;
|
|
15636
|
-
|
|
15889
|
+
debug15({
|
|
15637
15890
|
fixablePrVuls,
|
|
15638
15891
|
nonFixablePrVuls,
|
|
15639
15892
|
vulnerabilitiesOutsidePr,
|
|
@@ -15688,7 +15941,7 @@ ${contactUsMarkdown}`;
|
|
|
15688
15941
|
}
|
|
15689
15942
|
|
|
15690
15943
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
15691
|
-
var
|
|
15944
|
+
var debug16 = Debug15("mobbdev:handle-finished-analysis");
|
|
15692
15945
|
async function addFixCommentsForPr({
|
|
15693
15946
|
analysisId,
|
|
15694
15947
|
scm: _scm,
|
|
@@ -15700,7 +15953,7 @@ async function addFixCommentsForPr({
|
|
|
15700
15953
|
}
|
|
15701
15954
|
const scm = _scm;
|
|
15702
15955
|
const getAnalysisRes = await gqlClient.getAnalysis(analysisId);
|
|
15703
|
-
|
|
15956
|
+
debug16("getAnalysis %o", getAnalysisRes);
|
|
15704
15957
|
const {
|
|
15705
15958
|
vulnerabilityReport: {
|
|
15706
15959
|
projectId,
|
|
@@ -15810,8 +16063,8 @@ ${contextString}` : description;
|
|
|
15810
16063
|
|
|
15811
16064
|
// src/features/analysis/auto_pr_handler.ts
|
|
15812
16065
|
init_client_generates();
|
|
15813
|
-
import
|
|
15814
|
-
var
|
|
16066
|
+
import Debug16 from "debug";
|
|
16067
|
+
var debug17 = Debug16("mobbdev:handleAutoPr");
|
|
15815
16068
|
async function handleAutoPr(params) {
|
|
15816
16069
|
const {
|
|
15817
16070
|
gqlClient,
|
|
@@ -15832,7 +16085,7 @@ async function handleAutoPr(params) {
|
|
|
15832
16085
|
prId,
|
|
15833
16086
|
prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
|
|
15834
16087
|
});
|
|
15835
|
-
|
|
16088
|
+
debug17("auto pr analysis res %o", autoPrAnalysisRes);
|
|
15836
16089
|
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
|
|
15837
16090
|
createAutoPrSpinner.error({
|
|
15838
16091
|
text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
|
|
@@ -15854,14 +16107,14 @@ async function handleAutoPr(params) {
|
|
|
15854
16107
|
};
|
|
15855
16108
|
const callbackStates = ["Finished" /* Finished */];
|
|
15856
16109
|
if (polling) {
|
|
15857
|
-
|
|
16110
|
+
debug17("[handleAutoPr] Using POLLING mode for analysis state updates");
|
|
15858
16111
|
return await gqlClient.pollForAnalysisState({
|
|
15859
16112
|
analysisId,
|
|
15860
16113
|
callback,
|
|
15861
16114
|
callbackStates
|
|
15862
16115
|
});
|
|
15863
16116
|
} else {
|
|
15864
|
-
|
|
16117
|
+
debug17("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
|
|
15865
16118
|
return await gqlClient.subscribeToAnalysis({
|
|
15866
16119
|
subscribeToAnalysisParams: {
|
|
15867
16120
|
analysisId
|
|
@@ -15874,15 +16127,15 @@ async function handleAutoPr(params) {
|
|
|
15874
16127
|
|
|
15875
16128
|
// src/features/analysis/git.ts
|
|
15876
16129
|
init_GitService();
|
|
15877
|
-
import
|
|
15878
|
-
var
|
|
16130
|
+
import Debug17 from "debug";
|
|
16131
|
+
var debug18 = Debug17("mobbdev:git");
|
|
15879
16132
|
async function getGitInfo(srcDirPath) {
|
|
15880
|
-
|
|
16133
|
+
debug18("getting git info for %s", srcDirPath);
|
|
15881
16134
|
const gitService = new GitService(srcDirPath);
|
|
15882
16135
|
try {
|
|
15883
16136
|
const validationResult = await gitService.validateRepository();
|
|
15884
16137
|
if (!validationResult.isValid) {
|
|
15885
|
-
|
|
16138
|
+
debug18("folder is not a git repo");
|
|
15886
16139
|
return {
|
|
15887
16140
|
success: false,
|
|
15888
16141
|
hash: void 0,
|
|
@@ -15897,9 +16150,9 @@ async function getGitInfo(srcDirPath) {
|
|
|
15897
16150
|
};
|
|
15898
16151
|
} catch (e) {
|
|
15899
16152
|
if (e instanceof Error) {
|
|
15900
|
-
|
|
16153
|
+
debug18("failed to run git %o", e);
|
|
15901
16154
|
if (e.message.includes(" spawn ")) {
|
|
15902
|
-
|
|
16155
|
+
debug18("git cli not installed");
|
|
15903
16156
|
} else {
|
|
15904
16157
|
throw e;
|
|
15905
16158
|
}
|
|
@@ -15913,13 +16166,13 @@ init_configs();
|
|
|
15913
16166
|
import fs9 from "fs";
|
|
15914
16167
|
import path8 from "path";
|
|
15915
16168
|
import AdmZip from "adm-zip";
|
|
15916
|
-
import
|
|
16169
|
+
import Debug18 from "debug";
|
|
15917
16170
|
import { globby } from "globby";
|
|
15918
16171
|
import { isBinary as isBinary2 } from "istextorbinary";
|
|
15919
16172
|
import { simpleGit as simpleGit3 } from "simple-git";
|
|
15920
16173
|
import { parseStringPromise } from "xml2js";
|
|
15921
16174
|
import { z as z30 } from "zod";
|
|
15922
|
-
var
|
|
16175
|
+
var debug19 = Debug18("mobbdev:pack");
|
|
15923
16176
|
var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z30.object({
|
|
15924
16177
|
properties: z30.object({
|
|
15925
16178
|
entry: z30.array(
|
|
@@ -15941,7 +16194,7 @@ function getManifestFilesSuffixes() {
|
|
|
15941
16194
|
return ["package.json", "pom.xml"];
|
|
15942
16195
|
}
|
|
15943
16196
|
async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
15944
|
-
|
|
16197
|
+
debug19("pack folder %s", srcDirPath);
|
|
15945
16198
|
let git;
|
|
15946
16199
|
try {
|
|
15947
16200
|
git = simpleGit3({
|
|
@@ -15951,13 +16204,13 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15951
16204
|
});
|
|
15952
16205
|
await git.status();
|
|
15953
16206
|
} catch (e) {
|
|
15954
|
-
|
|
16207
|
+
debug19("failed to run git %o", e);
|
|
15955
16208
|
git = void 0;
|
|
15956
16209
|
if (e instanceof Error) {
|
|
15957
16210
|
if (e.message.includes(" spawn ")) {
|
|
15958
|
-
|
|
16211
|
+
debug19("git cli not installed");
|
|
15959
16212
|
} else if (e.message.includes("not a git repository")) {
|
|
15960
|
-
|
|
16213
|
+
debug19("folder is not a git repo");
|
|
15961
16214
|
} else {
|
|
15962
16215
|
throw e;
|
|
15963
16216
|
}
|
|
@@ -15972,9 +16225,9 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15972
16225
|
followSymbolicLinks: false,
|
|
15973
16226
|
dot: true
|
|
15974
16227
|
});
|
|
15975
|
-
|
|
16228
|
+
debug19("files found %d", filepaths.length);
|
|
15976
16229
|
const zip = new AdmZip();
|
|
15977
|
-
|
|
16230
|
+
debug19("compressing files");
|
|
15978
16231
|
for (const filepath of filepaths) {
|
|
15979
16232
|
const absFilepath = path8.join(srcDirPath, filepath.toString());
|
|
15980
16233
|
if (!isIncludeAllFiles) {
|
|
@@ -15983,12 +16236,12 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15983
16236
|
absFilepath.toString().replaceAll(path8.win32.sep, path8.posix.sep),
|
|
15984
16237
|
vulnFiles
|
|
15985
16238
|
)) {
|
|
15986
|
-
|
|
16239
|
+
debug19("ignoring %s because it is not a vulnerability file", filepath);
|
|
15987
16240
|
continue;
|
|
15988
16241
|
}
|
|
15989
16242
|
}
|
|
15990
16243
|
if (fs9.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
|
|
15991
|
-
|
|
16244
|
+
debug19(
|
|
15992
16245
|
"ignoring %s \u2014 file size exceeds MCP_MAX_FILE_SIZE (%d bytes)",
|
|
15993
16246
|
filepath,
|
|
15994
16247
|
MCP_MAX_FILE_SIZE
|
|
@@ -16006,16 +16259,16 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
16006
16259
|
data = fs9.readFileSync(absFilepath);
|
|
16007
16260
|
}
|
|
16008
16261
|
if (isBinary2(null, data)) {
|
|
16009
|
-
|
|
16262
|
+
debug19("ignoring %s because is seems to be a binary file", filepath);
|
|
16010
16263
|
continue;
|
|
16011
16264
|
}
|
|
16012
16265
|
zip.addFile(filepath.toString(), data);
|
|
16013
16266
|
}
|
|
16014
|
-
|
|
16267
|
+
debug19("get zip file buffer");
|
|
16015
16268
|
return zip.toBuffer();
|
|
16016
16269
|
}
|
|
16017
16270
|
async function repackFpr(fprPath) {
|
|
16018
|
-
|
|
16271
|
+
debug19("repack fpr file %s", fprPath);
|
|
16019
16272
|
const zipIn = new AdmZip(fprPath);
|
|
16020
16273
|
const zipOut = new AdmZip();
|
|
16021
16274
|
const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
|
|
@@ -16030,7 +16283,7 @@ async function repackFpr(fprPath) {
|
|
|
16030
16283
|
zipOut.addFile(realPath, buf);
|
|
16031
16284
|
}
|
|
16032
16285
|
}
|
|
16033
|
-
|
|
16286
|
+
debug19("get repacked zip file buffer");
|
|
16034
16287
|
return zipOut.toBuffer();
|
|
16035
16288
|
}
|
|
16036
16289
|
|
|
@@ -16101,7 +16354,7 @@ async function snykArticlePrompt() {
|
|
|
16101
16354
|
// src/features/analysis/scanners/checkmarx.ts
|
|
16102
16355
|
import { createRequire } from "module";
|
|
16103
16356
|
import chalk5 from "chalk";
|
|
16104
|
-
import
|
|
16357
|
+
import Debug20 from "debug";
|
|
16105
16358
|
import { existsSync } from "fs";
|
|
16106
16359
|
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
16107
16360
|
import { type } from "os";
|
|
@@ -16113,7 +16366,7 @@ var cxOperatingSystemSupportMessage = `Your operating system does not support ch
|
|
|
16113
16366
|
|
|
16114
16367
|
// src/utils/child_process.ts
|
|
16115
16368
|
import cp from "child_process";
|
|
16116
|
-
import
|
|
16369
|
+
import Debug19 from "debug";
|
|
16117
16370
|
import * as process2 from "process";
|
|
16118
16371
|
function createFork({ args, processPath, name }, options) {
|
|
16119
16372
|
const child = cp.fork(processPath, args, {
|
|
@@ -16131,16 +16384,16 @@ function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
|
|
|
16131
16384
|
return createChildProcess({ childProcess: child, name }, options);
|
|
16132
16385
|
}
|
|
16133
16386
|
function createChildProcess({ childProcess, name }, options) {
|
|
16134
|
-
const
|
|
16387
|
+
const debug24 = Debug19(`mobbdev:${name}`);
|
|
16135
16388
|
const { display } = options;
|
|
16136
16389
|
return new Promise((resolve, reject) => {
|
|
16137
16390
|
let out = "";
|
|
16138
16391
|
const onData = (chunk) => {
|
|
16139
|
-
|
|
16392
|
+
debug24(`chunk received from ${name} std ${chunk}`);
|
|
16140
16393
|
out += chunk;
|
|
16141
16394
|
};
|
|
16142
16395
|
if (!childProcess?.stdout || !childProcess?.stderr) {
|
|
16143
|
-
|
|
16396
|
+
debug24(`unable to fork ${name}`);
|
|
16144
16397
|
reject(new Error(`unable to fork ${name}`));
|
|
16145
16398
|
}
|
|
16146
16399
|
childProcess.stdout?.on("data", onData);
|
|
@@ -16150,18 +16403,18 @@ function createChildProcess({ childProcess, name }, options) {
|
|
|
16150
16403
|
childProcess.stderr?.pipe(process2.stderr);
|
|
16151
16404
|
}
|
|
16152
16405
|
childProcess.on("exit", (code) => {
|
|
16153
|
-
|
|
16406
|
+
debug24(`${name} exit code ${code}`);
|
|
16154
16407
|
resolve({ message: out, code });
|
|
16155
16408
|
});
|
|
16156
16409
|
childProcess.on("error", (err) => {
|
|
16157
|
-
|
|
16410
|
+
debug24(`${name} error %o`, err);
|
|
16158
16411
|
reject(err);
|
|
16159
16412
|
});
|
|
16160
16413
|
});
|
|
16161
16414
|
}
|
|
16162
16415
|
|
|
16163
16416
|
// src/features/analysis/scanners/checkmarx.ts
|
|
16164
|
-
var
|
|
16417
|
+
var debug20 = Debug20("mobbdev:checkmarx");
|
|
16165
16418
|
var moduleUrl;
|
|
16166
16419
|
if (typeof __filename !== "undefined") {
|
|
16167
16420
|
moduleUrl = __filename;
|
|
@@ -16220,14 +16473,14 @@ function validateCheckmarxInstallation() {
|
|
|
16220
16473
|
existsSync(getCheckmarxPath());
|
|
16221
16474
|
}
|
|
16222
16475
|
async function forkCheckmarx(args, { display }) {
|
|
16223
|
-
|
|
16476
|
+
debug20("fork checkmarx with args %o %s", args.join(" "), display);
|
|
16224
16477
|
return createSpawn(
|
|
16225
16478
|
{ args, processPath: getCheckmarxPath(), name: "checkmarx" },
|
|
16226
16479
|
{ display }
|
|
16227
16480
|
);
|
|
16228
16481
|
}
|
|
16229
16482
|
async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectName }, { skipPrompts = false }) {
|
|
16230
|
-
|
|
16483
|
+
debug20("get checkmarx report start %s %s", reportPath, repositoryRoot);
|
|
16231
16484
|
const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
|
|
16232
16485
|
display: false
|
|
16233
16486
|
});
|
|
@@ -16295,10 +16548,10 @@ async function validateCheckamxCredentials() {
|
|
|
16295
16548
|
// src/features/analysis/scanners/snyk.ts
|
|
16296
16549
|
import { createRequire as createRequire2 } from "module";
|
|
16297
16550
|
import chalk6 from "chalk";
|
|
16298
|
-
import
|
|
16551
|
+
import Debug21 from "debug";
|
|
16299
16552
|
import { createSpinner as createSpinner3 } from "nanospinner";
|
|
16300
16553
|
import open2 from "open";
|
|
16301
|
-
var
|
|
16554
|
+
var debug21 = Debug21("mobbdev:snyk");
|
|
16302
16555
|
var moduleUrl2;
|
|
16303
16556
|
if (typeof __filename !== "undefined") {
|
|
16304
16557
|
moduleUrl2 = __filename;
|
|
@@ -16320,13 +16573,13 @@ if (typeof __filename !== "undefined") {
|
|
|
16320
16573
|
var costumeRequire2 = createRequire2(moduleUrl2);
|
|
16321
16574
|
var SNYK_PATH = costumeRequire2.resolve("snyk/bin/snyk");
|
|
16322
16575
|
var SNYK_ARTICLE_URL = "https://docs.snyk.io/scan-using-snyk/snyk-code/configure-snyk-code#enable-snyk-code";
|
|
16323
|
-
|
|
16576
|
+
debug21("snyk executable path %s", SNYK_PATH);
|
|
16324
16577
|
async function forkSnyk(args, { display }) {
|
|
16325
|
-
|
|
16578
|
+
debug21("fork snyk with args %o %s", args, display);
|
|
16326
16579
|
return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
|
|
16327
16580
|
}
|
|
16328
16581
|
async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
16329
|
-
|
|
16582
|
+
debug21("get snyk report start %s %s", reportPath, repoRoot);
|
|
16330
16583
|
const config2 = await forkSnyk(["config"], { display: false });
|
|
16331
16584
|
const { message: configMessage } = config2;
|
|
16332
16585
|
if (!configMessage.includes("api: ")) {
|
|
@@ -16340,7 +16593,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
|
16340
16593
|
snykLoginSpinner.update({
|
|
16341
16594
|
text: "\u{1F513} Waiting for Snyk login to complete"
|
|
16342
16595
|
});
|
|
16343
|
-
|
|
16596
|
+
debug21("no token in the config %s", config2);
|
|
16344
16597
|
await forkSnyk(["auth"], { display: true });
|
|
16345
16598
|
snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
|
|
16346
16599
|
}
|
|
@@ -16350,12 +16603,12 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
|
16350
16603
|
{ display: true }
|
|
16351
16604
|
);
|
|
16352
16605
|
if (scanOutput.includes("Snyk Code is not supported for org")) {
|
|
16353
|
-
|
|
16606
|
+
debug21("snyk code is not enabled %s", scanOutput);
|
|
16354
16607
|
snykSpinner.error({ text: "\u{1F50D} Snyk configuration needed" });
|
|
16355
16608
|
const answer = await snykArticlePrompt();
|
|
16356
|
-
|
|
16609
|
+
debug21("answer %s", answer);
|
|
16357
16610
|
if (answer) {
|
|
16358
|
-
|
|
16611
|
+
debug21("opening the browser");
|
|
16359
16612
|
await open2(SNYK_ARTICLE_URL);
|
|
16360
16613
|
}
|
|
16361
16614
|
console.log(
|
|
@@ -16403,9 +16656,9 @@ async function downloadRepo({
|
|
|
16403
16656
|
}) {
|
|
16404
16657
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
16405
16658
|
const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
|
|
16406
|
-
|
|
16659
|
+
debug22("download repo %s %s %s", repoUrl, dirname);
|
|
16407
16660
|
const zipFilePath = path10.join(dirname, "repo.zip");
|
|
16408
|
-
|
|
16661
|
+
debug22("download URL: %s auth headers: %o", downloadUrl, authHeaders);
|
|
16409
16662
|
const response = await fetch4(downloadUrl, {
|
|
16410
16663
|
method: "GET",
|
|
16411
16664
|
headers: {
|
|
@@ -16413,7 +16666,7 @@ async function downloadRepo({
|
|
|
16413
16666
|
}
|
|
16414
16667
|
});
|
|
16415
16668
|
if (!response.ok) {
|
|
16416
|
-
|
|
16669
|
+
debug22("SCM zipball request failed %s %s", response.body, response.status);
|
|
16417
16670
|
repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
|
|
16418
16671
|
throw new Error(`Can't access ${chalk7.bold(repoUrl)}`);
|
|
16419
16672
|
}
|
|
@@ -16427,7 +16680,7 @@ async function downloadRepo({
|
|
|
16427
16680
|
if (!repoRoot) {
|
|
16428
16681
|
throw new Error("Repo root not found");
|
|
16429
16682
|
}
|
|
16430
|
-
|
|
16683
|
+
debug22("repo root %s", repoRoot);
|
|
16431
16684
|
repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
|
|
16432
16685
|
return path10.join(dirname, repoRoot);
|
|
16433
16686
|
}
|
|
@@ -16436,7 +16689,7 @@ var getReportUrl = ({
|
|
|
16436
16689
|
projectId,
|
|
16437
16690
|
fixReportId
|
|
16438
16691
|
}) => `${WEB_APP_URL}/organization/${organizationId}/project/${projectId}/report/${fixReportId}`;
|
|
16439
|
-
var
|
|
16692
|
+
var debug22 = Debug22("mobbdev:index");
|
|
16440
16693
|
async function runAnalysis(params, options) {
|
|
16441
16694
|
const tmpObj = tmp2.dirSync({
|
|
16442
16695
|
unsafeCleanup: true
|
|
@@ -16583,7 +16836,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16583
16836
|
polling,
|
|
16584
16837
|
baselineCommit
|
|
16585
16838
|
} = params;
|
|
16586
|
-
|
|
16839
|
+
debug22("start %s %s", dirname, repo);
|
|
16587
16840
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
16588
16841
|
skipPrompts = skipPrompts || ci;
|
|
16589
16842
|
const gqlClient = await getAuthenticatedGQLClient({
|
|
@@ -16623,8 +16876,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16623
16876
|
});
|
|
16624
16877
|
if (!isRepoAvailable) {
|
|
16625
16878
|
if (ci || !cloudScmLibType || !scmAuthUrl) {
|
|
16626
|
-
const
|
|
16627
|
-
throw new Error(
|
|
16879
|
+
const errorMessage3 = 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`;
|
|
16880
|
+
throw new Error(errorMessage3);
|
|
16628
16881
|
}
|
|
16629
16882
|
if (cloudScmLibType && scmAuthUrl) {
|
|
16630
16883
|
await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
|
|
@@ -16656,8 +16909,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16656
16909
|
);
|
|
16657
16910
|
}
|
|
16658
16911
|
const { sha } = getReferenceDataRes.gitReference;
|
|
16659
|
-
|
|
16660
|
-
|
|
16912
|
+
debug22("project id %s", projectId);
|
|
16913
|
+
debug22("default branch %s", reference);
|
|
16661
16914
|
if (command === "scan") {
|
|
16662
16915
|
reportPath = await getReport(
|
|
16663
16916
|
{
|
|
@@ -16994,7 +17247,7 @@ async function _digestReport({
|
|
|
16994
17247
|
text: progressMassages.processingVulnerabilityReportSuccess
|
|
16995
17248
|
});
|
|
16996
17249
|
if (polling) {
|
|
16997
|
-
|
|
17250
|
+
debug22(
|
|
16998
17251
|
"[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
|
|
16999
17252
|
);
|
|
17000
17253
|
console.log(
|
|
@@ -17009,7 +17262,7 @@ async function _digestReport({
|
|
|
17009
17262
|
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
17010
17263
|
});
|
|
17011
17264
|
} else {
|
|
17012
|
-
|
|
17265
|
+
debug22(
|
|
17013
17266
|
"[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
|
|
17014
17267
|
);
|
|
17015
17268
|
console.log(
|
|
@@ -17034,9 +17287,9 @@ async function _digestReport({
|
|
|
17034
17287
|
});
|
|
17035
17288
|
return vulnFiles;
|
|
17036
17289
|
} catch (e) {
|
|
17037
|
-
const
|
|
17290
|
+
const errorMessage3 = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
|
|
17038
17291
|
digestSpinner.error({
|
|
17039
|
-
text:
|
|
17292
|
+
text: errorMessage3
|
|
17040
17293
|
});
|
|
17041
17294
|
throw e;
|
|
17042
17295
|
}
|
|
@@ -17073,7 +17326,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
17073
17326
|
});
|
|
17074
17327
|
};
|
|
17075
17328
|
if (polling) {
|
|
17076
|
-
|
|
17329
|
+
debug22(
|
|
17077
17330
|
"[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
|
|
17078
17331
|
);
|
|
17079
17332
|
console.log(
|
|
@@ -17087,7 +17340,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
17087
17340
|
callbackStates: ["Finished" /* Finished */]
|
|
17088
17341
|
});
|
|
17089
17342
|
} else {
|
|
17090
|
-
|
|
17343
|
+
debug22(
|
|
17091
17344
|
"[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
|
|
17092
17345
|
);
|
|
17093
17346
|
console.log(
|
|
@@ -17391,11 +17644,11 @@ function throwRepoUrlErrorMessage({
|
|
|
17391
17644
|
repoUrl,
|
|
17392
17645
|
command
|
|
17393
17646
|
}) {
|
|
17394
|
-
const
|
|
17647
|
+
const errorMessage3 = error.issues[error.issues.length - 1]?.message;
|
|
17395
17648
|
const formattedErrorMessage = `
|
|
17396
17649
|
Error: ${chalk9.bold(
|
|
17397
17650
|
repoUrl
|
|
17398
|
-
)} is ${
|
|
17651
|
+
)} is ${errorMessage3}
|
|
17399
17652
|
Example:
|
|
17400
17653
|
mobbdev ${command} -r ${chalk9.bold(
|
|
17401
17654
|
"https://github.com/WebGoat/WebGoat"
|
|
@@ -17523,7 +17776,7 @@ import { spawn } from "child_process";
|
|
|
17523
17776
|
import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
17524
17777
|
import * as os8 from "os";
|
|
17525
17778
|
import path24 from "path";
|
|
17526
|
-
import { setTimeout as
|
|
17779
|
+
import { setTimeout as sleep3 } from "timers/promises";
|
|
17527
17780
|
import Configstore3 from "configstore";
|
|
17528
17781
|
|
|
17529
17782
|
// src/features/analysis/skill_quarantine/runQuarantineCheck.ts
|
|
@@ -19410,7 +19663,7 @@ function createLogger(config2) {
|
|
|
19410
19663
|
const info = pinoLogger.info.bind(pinoLogger);
|
|
19411
19664
|
const warn = pinoLogger.warn.bind(pinoLogger);
|
|
19412
19665
|
const error = pinoLogger.error.bind(pinoLogger);
|
|
19413
|
-
const
|
|
19666
|
+
const debug24 = pinoLogger.debug.bind(pinoLogger);
|
|
19414
19667
|
function heartbeat(message, data) {
|
|
19415
19668
|
pinoLogger.info({ data, heartbeat: true }, message);
|
|
19416
19669
|
}
|
|
@@ -19453,7 +19706,7 @@ function createLogger(config2) {
|
|
|
19453
19706
|
info,
|
|
19454
19707
|
warn,
|
|
19455
19708
|
error,
|
|
19456
|
-
debug:
|
|
19709
|
+
debug: debug24,
|
|
19457
19710
|
heartbeat,
|
|
19458
19711
|
timed,
|
|
19459
19712
|
flushLogs,
|
|
@@ -19468,7 +19721,7 @@ function createLogger(config2) {
|
|
|
19468
19721
|
|
|
19469
19722
|
// src/features/claude_code/hook_logger.ts
|
|
19470
19723
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
19471
|
-
var CLI_VERSION = true ? "1.4.
|
|
19724
|
+
var CLI_VERSION = true ? "1.4.23" : "unknown";
|
|
19472
19725
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
19473
19726
|
var claudeCodeVersion;
|
|
19474
19727
|
function buildDdTags() {
|
|
@@ -19996,6 +20249,12 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
|
|
|
19996
20249
|
sanitize
|
|
19997
20250
|
})
|
|
19998
20251
|
);
|
|
20252
|
+
if (result.degenerate?.length) {
|
|
20253
|
+
log2.warn(
|
|
20254
|
+
{ data: degenerateRecordsLogFields(result.degenerate) },
|
|
20255
|
+
DEGENERATE_RECORDS_LOG_MESSAGE
|
|
20256
|
+
);
|
|
20257
|
+
}
|
|
19999
20258
|
if (result.ok) {
|
|
20000
20259
|
const lastRawEntry = rawEntries[rawEntries.length - 1];
|
|
20001
20260
|
const cursor = {
|
|
@@ -20566,7 +20825,7 @@ async function startDaemon() {
|
|
|
20566
20825
|
},
|
|
20567
20826
|
"daemon poll cycle"
|
|
20568
20827
|
);
|
|
20569
|
-
await
|
|
20828
|
+
await sleep3(DAEMON_POLL_INTERVAL_MS);
|
|
20570
20829
|
}
|
|
20571
20830
|
}
|
|
20572
20831
|
async function acquirePidFile() {
|
|
@@ -21289,7 +21548,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21289
21548
|
{ data }
|
|
21290
21549
|
);
|
|
21291
21550
|
if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
|
|
21292
|
-
const
|
|
21551
|
+
const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
|
|
21293
21552
|
logError(`[${scanContext}] GraphQL: Analysis failed`, {
|
|
21294
21553
|
analysisId: data.analysis?.id,
|
|
21295
21554
|
state: data.analysis?.state,
|
|
@@ -21297,7 +21556,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21297
21556
|
...this.getErrorContext()
|
|
21298
21557
|
});
|
|
21299
21558
|
subscription.unsubscribe();
|
|
21300
|
-
reject(new Error(
|
|
21559
|
+
reject(new Error(errorMessage3));
|
|
21301
21560
|
return;
|
|
21302
21561
|
}
|
|
21303
21562
|
if (callbackStates.includes(data.analysis?.state)) {
|
|
@@ -21409,17 +21668,17 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21409
21668
|
});
|
|
21410
21669
|
return createdProject.createProject.projectId;
|
|
21411
21670
|
} catch (createError) {
|
|
21412
|
-
const
|
|
21413
|
-
const isConstraintViolation =
|
|
21671
|
+
const errorMessage3 = createError instanceof Error ? createError.message : String(createError);
|
|
21672
|
+
const isConstraintViolation = errorMessage3.includes(
|
|
21414
21673
|
"duplicate key value violates unique constraint"
|
|
21415
|
-
) &&
|
|
21674
|
+
) && errorMessage3.includes("project_name_organization_id_key");
|
|
21416
21675
|
if (isConstraintViolation) {
|
|
21417
21676
|
logDebug(
|
|
21418
21677
|
"[GraphQL] Project creation failed due to constraint violation, retrying fetch",
|
|
21419
21678
|
{
|
|
21420
21679
|
organizationId: organization.id,
|
|
21421
21680
|
projectName,
|
|
21422
|
-
error:
|
|
21681
|
+
error: errorMessage3
|
|
21423
21682
|
}
|
|
21424
21683
|
);
|
|
21425
21684
|
const retryOrgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
|
|
@@ -22829,8 +23088,8 @@ var McpServer = class {
|
|
|
22829
23088
|
});
|
|
22830
23089
|
return serializedResponse;
|
|
22831
23090
|
} catch (error) {
|
|
22832
|
-
const
|
|
22833
|
-
logError(`Error executing tool ${name}: ${
|
|
23091
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
23092
|
+
logError(`Error executing tool ${name}: ${errorMessage3}`, {
|
|
22834
23093
|
error,
|
|
22835
23094
|
toolName: name,
|
|
22836
23095
|
args
|
|
@@ -22885,8 +23144,8 @@ var McpServer = class {
|
|
|
22885
23144
|
});
|
|
22886
23145
|
return response;
|
|
22887
23146
|
} catch (error) {
|
|
22888
|
-
const
|
|
22889
|
-
logError(`Error generating prompt ${name}: ${
|
|
23147
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
23148
|
+
logError(`Error generating prompt ${name}: ${errorMessage3}`, {
|
|
22890
23149
|
error,
|
|
22891
23150
|
promptName: name,
|
|
22892
23151
|
args
|
|
@@ -23023,8 +23282,8 @@ var BasePrompt = class {
|
|
|
23023
23282
|
const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
|
|
23024
23283
|
return message;
|
|
23025
23284
|
});
|
|
23026
|
-
const
|
|
23027
|
-
throw new Error(
|
|
23285
|
+
const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
|
|
23286
|
+
throw new Error(errorMessage3);
|
|
23028
23287
|
}
|
|
23029
23288
|
throw error;
|
|
23030
23289
|
}
|
|
@@ -24733,9 +24992,9 @@ async function validatePath(inputPath) {
|
|
|
24733
24992
|
logDebug("Stored validated path in WorkspaceService", { inputPath });
|
|
24734
24993
|
return { isValid: true, path: inputPath };
|
|
24735
24994
|
} catch (error) {
|
|
24736
|
-
const
|
|
24737
|
-
logError(
|
|
24738
|
-
return { isValid: false, error:
|
|
24995
|
+
const errorMessage3 = `Path does not exist or is not accessible: ${inputPath}`;
|
|
24996
|
+
logError(errorMessage3, { error });
|
|
24997
|
+
return { isValid: false, error: errorMessage3, path: inputPath };
|
|
24739
24998
|
}
|
|
24740
24999
|
}
|
|
24741
25000
|
|
|
@@ -24773,8 +25032,8 @@ var BaseTool = class {
|
|
|
24773
25032
|
const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
|
|
24774
25033
|
return message;
|
|
24775
25034
|
});
|
|
24776
|
-
const
|
|
24777
|
-
throw new Error(
|
|
25035
|
+
const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
|
|
25036
|
+
throw new Error(errorMessage3);
|
|
24778
25037
|
}
|
|
24779
25038
|
throw error;
|
|
24780
25039
|
}
|
|
@@ -25746,9 +26005,9 @@ var LocalMobbFolderService = class {
|
|
|
25746
26005
|
});
|
|
25747
26006
|
return mobbFolderPath;
|
|
25748
26007
|
} catch (error) {
|
|
25749
|
-
const
|
|
25750
|
-
logError(
|
|
25751
|
-
throw new Error(
|
|
26008
|
+
const errorMessage3 = `Failed to get/create .mobb folder: ${error}`;
|
|
26009
|
+
logError(errorMessage3, { repoPath: this.repoPath, error });
|
|
26010
|
+
throw new Error(errorMessage3);
|
|
25752
26011
|
}
|
|
25753
26012
|
}
|
|
25754
26013
|
/**
|
|
@@ -25909,8 +26168,8 @@ var LocalMobbFolderService = class {
|
|
|
25909
26168
|
message: `Patch saved successfully as ${uniqueFileName}`
|
|
25910
26169
|
};
|
|
25911
26170
|
} catch (error) {
|
|
25912
|
-
const
|
|
25913
|
-
logError(
|
|
26171
|
+
const errorMessage3 = `Failed to save patch for fix ${fix.id}: ${error}`;
|
|
26172
|
+
logError(errorMessage3, {
|
|
25914
26173
|
fixId: fix.id,
|
|
25915
26174
|
fileName,
|
|
25916
26175
|
severity,
|
|
@@ -25920,8 +26179,8 @@ var LocalMobbFolderService = class {
|
|
|
25920
26179
|
});
|
|
25921
26180
|
return {
|
|
25922
26181
|
success: false,
|
|
25923
|
-
error:
|
|
25924
|
-
message:
|
|
26182
|
+
error: errorMessage3,
|
|
26183
|
+
message: errorMessage3
|
|
25925
26184
|
};
|
|
25926
26185
|
}
|
|
25927
26186
|
}
|
|
@@ -26011,12 +26270,12 @@ var LocalMobbFolderService = class {
|
|
|
26011
26270
|
message: `Fix details logged to patchInfo.md`
|
|
26012
26271
|
};
|
|
26013
26272
|
} catch (error) {
|
|
26014
|
-
const
|
|
26015
|
-
logError(
|
|
26273
|
+
const errorMessage3 = `Failed to log patch info: ${error}`;
|
|
26274
|
+
logError(errorMessage3, { fixId: fix.id, error });
|
|
26016
26275
|
return {
|
|
26017
26276
|
success: false,
|
|
26018
|
-
error:
|
|
26019
|
-
message:
|
|
26277
|
+
error: errorMessage3,
|
|
26278
|
+
message: errorMessage3
|
|
26020
26279
|
};
|
|
26021
26280
|
}
|
|
26022
26281
|
}
|
|
@@ -26711,12 +26970,12 @@ var PatchApplicationService = class {
|
|
|
26711
26970
|
failedFixes.push({ fix, error: result.error || "Unknown error" });
|
|
26712
26971
|
}
|
|
26713
26972
|
} catch (error) {
|
|
26714
|
-
const
|
|
26973
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
26715
26974
|
logError(`[${scanContext}] Failed to apply standalone fix ${fix.id}`, {
|
|
26716
|
-
error:
|
|
26975
|
+
error: errorMessage3,
|
|
26717
26976
|
issueType: fix.safeIssueType
|
|
26718
26977
|
});
|
|
26719
|
-
failedFixes.push({ fix, error:
|
|
26978
|
+
failedFixes.push({ fix, error: errorMessage3 });
|
|
26720
26979
|
}
|
|
26721
26980
|
}
|
|
26722
26981
|
}
|
|
@@ -26767,17 +27026,17 @@ var PatchApplicationService = class {
|
|
|
26767
27026
|
return { success: false, error: result.error };
|
|
26768
27027
|
}
|
|
26769
27028
|
} catch (error) {
|
|
26770
|
-
const
|
|
27029
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
26771
27030
|
logInfo(
|
|
26772
27031
|
`[${scanContext}] Fix ${fix.id} threw exception for ${targetFile}, trying next option if available`,
|
|
26773
27032
|
{
|
|
26774
|
-
error:
|
|
27033
|
+
error: errorMessage3,
|
|
26775
27034
|
issueType: fix.safeIssueType,
|
|
26776
27035
|
attemptNumber,
|
|
26777
27036
|
remainingOptions: totalAttempts - attemptNumber
|
|
26778
27037
|
}
|
|
26779
27038
|
);
|
|
26780
|
-
return { success: false, error:
|
|
27039
|
+
return { success: false, error: errorMessage3 };
|
|
26781
27040
|
}
|
|
26782
27041
|
}
|
|
26783
27042
|
/**
|
|
@@ -27281,18 +27540,18 @@ var PatchApplicationService = class {
|
|
|
27281
27540
|
);
|
|
27282
27541
|
return { success: true };
|
|
27283
27542
|
} catch (patchError) {
|
|
27284
|
-
const
|
|
27543
|
+
const errorMessage3 = patchError instanceof Error ? patchError.message : String(patchError);
|
|
27285
27544
|
logError(
|
|
27286
27545
|
`[${scanContext}] In-memory patch application failed for fix ${fix.id}`,
|
|
27287
27546
|
{
|
|
27288
|
-
errorMessage,
|
|
27547
|
+
errorMessage: errorMessage3,
|
|
27289
27548
|
patchErrorType: patchError instanceof Error ? patchError.name : typeof patchError,
|
|
27290
27549
|
targetFiles
|
|
27291
27550
|
}
|
|
27292
27551
|
);
|
|
27293
27552
|
return {
|
|
27294
27553
|
success: false,
|
|
27295
|
-
error: `Patch application failed: ${
|
|
27554
|
+
error: `Patch application failed: ${errorMessage3}`
|
|
27296
27555
|
};
|
|
27297
27556
|
}
|
|
27298
27557
|
}
|
|
@@ -27912,22 +28171,22 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
27912
28171
|
this.updateFilesScanTimestamps(filesToScan);
|
|
27913
28172
|
this.isInitialScanComplete = true;
|
|
27914
28173
|
} catch (error) {
|
|
27915
|
-
const
|
|
27916
|
-
if (
|
|
28174
|
+
const errorMessage3 = error.message;
|
|
28175
|
+
if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
|
|
27917
28176
|
logError(
|
|
27918
28177
|
`[${scanContext}] Periodic scan skipped due to authentication failure. Please re-authenticate by running a manual scan.`,
|
|
27919
28178
|
{
|
|
27920
|
-
error:
|
|
28179
|
+
error: errorMessage3
|
|
27921
28180
|
}
|
|
27922
28181
|
);
|
|
27923
28182
|
this.hasAuthenticationFailed = true;
|
|
27924
28183
|
return;
|
|
27925
28184
|
}
|
|
27926
|
-
if (
|
|
28185
|
+
if (errorMessage3.includes("ReportInitializationError")) {
|
|
27927
28186
|
logError(
|
|
27928
28187
|
`[${scanContext}] Periodic scan failed during report initialization`,
|
|
27929
28188
|
{
|
|
27930
|
-
error:
|
|
28189
|
+
error: errorMessage3
|
|
27931
28190
|
}
|
|
27932
28191
|
);
|
|
27933
28192
|
return;
|
|
@@ -28162,12 +28421,12 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
28162
28421
|
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
28163
28422
|
this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
|
|
28164
28423
|
} catch (error) {
|
|
28165
|
-
const
|
|
28166
|
-
if (
|
|
28424
|
+
const errorMessage3 = error.message;
|
|
28425
|
+
if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
|
|
28167
28426
|
logError(
|
|
28168
28427
|
`[${scanContext}] Failed to create authenticated client due to authentication failure`,
|
|
28169
28428
|
{
|
|
28170
|
-
error:
|
|
28429
|
+
error: errorMessage3
|
|
28171
28430
|
}
|
|
28172
28431
|
);
|
|
28173
28432
|
this.hasAuthenticationFailed = true;
|
|
@@ -30037,13 +30296,13 @@ var parseArgs = async (args) => {
|
|
|
30037
30296
|
};
|
|
30038
30297
|
|
|
30039
30298
|
// src/index.ts
|
|
30040
|
-
var
|
|
30299
|
+
var debug23 = Debug23("mobbdev:index");
|
|
30041
30300
|
async function run() {
|
|
30042
30301
|
return parseArgs(hideBin(process.argv));
|
|
30043
30302
|
}
|
|
30044
30303
|
(async () => {
|
|
30045
30304
|
try {
|
|
30046
|
-
|
|
30305
|
+
debug23("Bugsy CLI v%s running...", packageJson.version);
|
|
30047
30306
|
await run();
|
|
30048
30307
|
process.exit(0);
|
|
30049
30308
|
} catch (err) {
|