mobbdev 1.0.114 → 1.0.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +182 -43
- package/package.json +17 -17
package/dist/index.mjs
CHANGED
|
@@ -392,6 +392,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
392
392
|
IssueType_Enum2["HeapInspection"] = "HEAP_INSPECTION";
|
|
393
393
|
IssueType_Enum2["HtmlCommentInJsp"] = "HTML_COMMENT_IN_JSP";
|
|
394
394
|
IssueType_Enum2["HttpOnlyCookie"] = "HTTP_ONLY_COOKIE";
|
|
395
|
+
IssueType_Enum2["HttpParameterPollution"] = "HTTP_PARAMETER_POLLUTION";
|
|
395
396
|
IssueType_Enum2["HttpResponseSplitting"] = "HTTP_RESPONSE_SPLITTING";
|
|
396
397
|
IssueType_Enum2["IframeWithoutSandbox"] = "IFRAME_WITHOUT_SANDBOX";
|
|
397
398
|
IssueType_Enum2["ImproperExceptionHandling"] = "IMPROPER_EXCEPTION_HANDLING";
|
|
@@ -445,6 +446,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
445
446
|
IssueType_Enum2["SqlInjection"] = "SQL_Injection";
|
|
446
447
|
IssueType_Enum2["Ssrf"] = "SSRF";
|
|
447
448
|
IssueType_Enum2["StringFormatMisuse"] = "STRING_FORMAT_MISUSE";
|
|
449
|
+
IssueType_Enum2["StringTerminationError"] = "STRING_TERMINATION_ERROR";
|
|
448
450
|
IssueType_Enum2["SystemExitShouldReraise"] = "SYSTEM_EXIT_SHOULD_RERAISE";
|
|
449
451
|
IssueType_Enum2["SystemInformationLeak"] = "SYSTEM_INFORMATION_LEAK";
|
|
450
452
|
IssueType_Enum2["SystemInformationLeakExternal"] = "SYSTEM_INFORMATION_LEAK_EXTERNAL";
|
|
@@ -1459,6 +1461,14 @@ var fixDetailsData = {
|
|
|
1459
1461
|
["BUFFER_OVERFLOW" /* BufferOverflow */]: {
|
|
1460
1462
|
issueDescription: "Buffer Overflow occurs when a program writes data beyond the allocated memory space, leading to unexpected behavior or security vulnerabilities.",
|
|
1461
1463
|
fixInstructions: "Implement proper input validation and bounds checking to prevent buffer overflows. Use safe string manipulation functions and ensure that the buffer size is properly managed."
|
|
1464
|
+
},
|
|
1465
|
+
["STRING_TERMINATION_ERROR" /* StringTerminationError */]: {
|
|
1466
|
+
issueDescription: "String Termination Error occurs when a string is not properly terminated, leading to unexpected behavior or security vulnerabilities.",
|
|
1467
|
+
fixInstructions: "Implement proper input validation and bounds checking to prevent string termination errors. Use safe string manipulation functions and ensure that the buffer size is properly managed."
|
|
1468
|
+
},
|
|
1469
|
+
["HTTP_PARAMETER_POLLUTION" /* HttpParameterPollution */]: {
|
|
1470
|
+
issueDescription: "HTTP Parameter Pollution occurs when an attacker can manipulate the parameters of an HTTP request to change the behavior of the server.",
|
|
1471
|
+
fixInstructions: "Implement proper input validation and bounds checking to prevent HTTP parameter pollution. Use safe string manipulation functions and ensure that the buffer size is properly managed."
|
|
1462
1472
|
}
|
|
1463
1473
|
};
|
|
1464
1474
|
|
|
@@ -1574,7 +1584,9 @@ var issueTypeMap = {
|
|
|
1574
1584
|
["UNNECESSARY_IMPORTS" /* UnnecessaryImports */]: "Unnecessary Imports",
|
|
1575
1585
|
["REDOS" /* Redos */]: "Regular Expression Denial of Service",
|
|
1576
1586
|
["DO_NOT_THROW_GENERIC_EXCEPTION" /* DoNotThrowGenericException */]: "Do Not Throw Generic Exception",
|
|
1577
|
-
["BUFFER_OVERFLOW" /* BufferOverflow */]: "Buffer Overflow"
|
|
1587
|
+
["BUFFER_OVERFLOW" /* BufferOverflow */]: "Buffer Overflow",
|
|
1588
|
+
["STRING_TERMINATION_ERROR" /* StringTerminationError */]: "String Termination Error",
|
|
1589
|
+
["HTTP_PARAMETER_POLLUTION" /* HttpParameterPollution */]: "HTTP Parameter Pollution"
|
|
1578
1590
|
};
|
|
1579
1591
|
var issueTypeZ = z.nativeEnum(IssueType_Enum);
|
|
1580
1592
|
var getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -5165,9 +5177,7 @@ var MCP_PERIODIC_CHECK_INTERVAL = 15 * 60 * 1e3;
|
|
|
5165
5177
|
var MCP_DEFAULT_MAX_FILES_TO_SCAN = 10;
|
|
5166
5178
|
var MCP_REPORT_ID_EXPIRATION_MS = 2 * 60 * 60 * 1e3;
|
|
5167
5179
|
var MCP_TOOLS_BROWSER_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
|
|
5168
|
-
var
|
|
5169
|
-
var MCP_TOOL_FETCH_AVAILABLE_FIXES = "fetch_available_fixes";
|
|
5170
|
-
var MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES = "scan_and_fix_vulnerabilities";
|
|
5180
|
+
var MCP_DEFAULT_LIMIT = 3;
|
|
5171
5181
|
|
|
5172
5182
|
// src/features/analysis/scm/FileUtils.ts
|
|
5173
5183
|
import fs2 from "fs";
|
|
@@ -5566,6 +5576,27 @@ var GitService = class {
|
|
|
5566
5576
|
throw new Error(errorMessage);
|
|
5567
5577
|
}
|
|
5568
5578
|
}
|
|
5579
|
+
/**
|
|
5580
|
+
* Gets both the current commit hash and current branch name
|
|
5581
|
+
*/
|
|
5582
|
+
async getCurrentCommitAndBranch() {
|
|
5583
|
+
this.log("Getting current commit hash and branch", "debug");
|
|
5584
|
+
try {
|
|
5585
|
+
const [hash, branch] = await Promise.all([
|
|
5586
|
+
this.git.revparse(["HEAD"]),
|
|
5587
|
+
this.git.revparse(["--abbrev-ref", "HEAD"])
|
|
5588
|
+
]);
|
|
5589
|
+
this.log("Current commit hash and branch retrieved", "debug", {
|
|
5590
|
+
hash,
|
|
5591
|
+
branch
|
|
5592
|
+
});
|
|
5593
|
+
return { hash, branch };
|
|
5594
|
+
} catch (error) {
|
|
5595
|
+
const errorMessage = `Failed to get current commit hash and branch: ${error.message}`;
|
|
5596
|
+
this.log(errorMessage, "error", { error });
|
|
5597
|
+
return { hash: "", branch: "" };
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5569
5600
|
/**
|
|
5570
5601
|
* Gets the remote repository URL
|
|
5571
5602
|
*/
|
|
@@ -5595,24 +5626,37 @@ var GitService = class {
|
|
|
5595
5626
|
}
|
|
5596
5627
|
}
|
|
5597
5628
|
/**
|
|
5598
|
-
* Gets the maxFiles most recently changed files
|
|
5629
|
+
* Gets the maxFiles most recently changed files, starting with current changes and then from commit history
|
|
5599
5630
|
*/
|
|
5600
5631
|
async getRecentlyChangedFiles({
|
|
5601
5632
|
maxFiles = MCP_DEFAULT_MAX_FILES_TO_SCAN
|
|
5602
5633
|
}) {
|
|
5603
5634
|
this.log(
|
|
5604
|
-
`Getting the ${maxFiles} most recently changed files
|
|
5635
|
+
`Getting the ${maxFiles} most recently changed files, starting with current changes`,
|
|
5605
5636
|
"debug"
|
|
5606
5637
|
);
|
|
5607
5638
|
try {
|
|
5639
|
+
const currentChanges = await this.getChangedFiles();
|
|
5608
5640
|
const gitRoot = await this.git.revparse(["--show-toplevel"]);
|
|
5609
5641
|
const relativePathFromGitRoot = path2.relative(
|
|
5610
5642
|
gitRoot,
|
|
5611
5643
|
this.repositoryPath
|
|
5612
5644
|
);
|
|
5613
5645
|
const fileSet = /* @__PURE__ */ new Set();
|
|
5614
|
-
const files = [];
|
|
5615
5646
|
let commitsProcessed = 0;
|
|
5647
|
+
for (const file of currentChanges.files) {
|
|
5648
|
+
if (fileSet.size >= maxFiles) {
|
|
5649
|
+
break;
|
|
5650
|
+
}
|
|
5651
|
+
const fullPath = path2.join(this.repositoryPath, file);
|
|
5652
|
+
if (FileUtils.shouldPackFile(fullPath) && !file.startsWith("..")) {
|
|
5653
|
+
fileSet.add(file);
|
|
5654
|
+
}
|
|
5655
|
+
}
|
|
5656
|
+
this.log(`Added ${fileSet.size} files from current changes`, "debug", {
|
|
5657
|
+
filesFromCurrentChanges: fileSet.size,
|
|
5658
|
+
currentChangesTotal: currentChanges.files.length
|
|
5659
|
+
});
|
|
5616
5660
|
const logResult = await this.git.log({
|
|
5617
5661
|
maxCount: maxFiles * 5,
|
|
5618
5662
|
// 5 times the max files to scan to ensure we find enough files
|
|
@@ -5625,7 +5669,7 @@ var GitService = class {
|
|
|
5625
5669
|
}
|
|
5626
5670
|
});
|
|
5627
5671
|
for (const commit of logResult.all) {
|
|
5628
|
-
if (
|
|
5672
|
+
if (fileSet.size >= maxFiles) {
|
|
5629
5673
|
break;
|
|
5630
5674
|
}
|
|
5631
5675
|
commitsProcessed++;
|
|
@@ -5637,7 +5681,7 @@ var GitService = class {
|
|
|
5637
5681
|
]);
|
|
5638
5682
|
const commitFiles = filesOutput.split("\n").filter((file) => file.trim() !== "");
|
|
5639
5683
|
for (const file of commitFiles) {
|
|
5640
|
-
if (
|
|
5684
|
+
if (fileSet.size >= maxFiles) {
|
|
5641
5685
|
break;
|
|
5642
5686
|
}
|
|
5643
5687
|
const gitRelativePath = file.trim();
|
|
@@ -5657,7 +5701,6 @@ var GitService = class {
|
|
|
5657
5701
|
this.log(`Considering file: ${adjustedPath}`, "debug");
|
|
5658
5702
|
if (!fileSet.has(adjustedPath) && FileUtils.shouldPackFile(path2.join(gitRoot, gitRelativePath)) && !adjustedPath.startsWith("..")) {
|
|
5659
5703
|
fileSet.add(adjustedPath);
|
|
5660
|
-
files.push(adjustedPath);
|
|
5661
5704
|
}
|
|
5662
5705
|
}
|
|
5663
5706
|
} catch (showError) {
|
|
@@ -5666,6 +5709,7 @@ var GitService = class {
|
|
|
5666
5709
|
});
|
|
5667
5710
|
}
|
|
5668
5711
|
}
|
|
5712
|
+
const files = Array.from(fileSet);
|
|
5669
5713
|
this.log("Recently changed files retrieved", "info", {
|
|
5670
5714
|
fileCount: files.length,
|
|
5671
5715
|
commitsProcessed,
|
|
@@ -11865,7 +11909,7 @@ var McpGQLClient = class {
|
|
|
11865
11909
|
}
|
|
11866
11910
|
async getLatestReportByRepoUrl({
|
|
11867
11911
|
repoUrl,
|
|
11868
|
-
limit =
|
|
11912
|
+
limit = MCP_DEFAULT_LIMIT,
|
|
11869
11913
|
offset = 0
|
|
11870
11914
|
}) {
|
|
11871
11915
|
try {
|
|
@@ -11916,7 +11960,7 @@ var McpGQLClient = class {
|
|
|
11916
11960
|
}
|
|
11917
11961
|
async getReportFixesPaginated({
|
|
11918
11962
|
reportId,
|
|
11919
|
-
limit =
|
|
11963
|
+
limit = MCP_DEFAULT_LIMIT,
|
|
11920
11964
|
offset = 0,
|
|
11921
11965
|
issueType,
|
|
11922
11966
|
severity
|
|
@@ -12006,6 +12050,11 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
12006
12050
|
return new McpGQLClient({ apiKey: newApiToken, type: "apiKey" });
|
|
12007
12051
|
}
|
|
12008
12052
|
|
|
12053
|
+
// src/mcp/tools/toolNames.ts
|
|
12054
|
+
var MCP_TOOL_CHECK_FOR_NEW_AVAILABLE_FIXES = "check_for_new_available_fixes";
|
|
12055
|
+
var MCP_TOOL_FETCH_AVAILABLE_FIXES = "fetch_available_fixes";
|
|
12056
|
+
var MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES = "scan_and_fix_vulnerabilities";
|
|
12057
|
+
|
|
12009
12058
|
// src/mcp/core/ToolRegistry.ts
|
|
12010
12059
|
var ToolRegistry = class {
|
|
12011
12060
|
constructor() {
|
|
@@ -12377,6 +12426,47 @@ function friendlyType(s) {
|
|
|
12377
12426
|
}
|
|
12378
12427
|
var noFixesReturnedForParameters = `No fixes returned for the given offset and limit parameters.
|
|
12379
12428
|
`;
|
|
12429
|
+
var noFixesReturnedForParametersWithGuidance = ({
|
|
12430
|
+
offset,
|
|
12431
|
+
limit,
|
|
12432
|
+
totalCount,
|
|
12433
|
+
currentTool
|
|
12434
|
+
}) => `## No Fixes Returned for Current Parameters
|
|
12435
|
+
|
|
12436
|
+
**\u{1F4C4} Current Request:**
|
|
12437
|
+
- **Page:** ${Math.floor(offset / limit) + 1}
|
|
12438
|
+
- **Offset:** ${offset}
|
|
12439
|
+
- **Limit:** ${limit}
|
|
12440
|
+
|
|
12441
|
+
**\u274C Result:** No fixes returned for the given offset and limit parameters.
|
|
12442
|
+
|
|
12443
|
+
**\u2139\uFE0F Available Fixes:** ${totalCount} total fixes are available, but your current offset (${offset}) is beyond the available range.
|
|
12444
|
+
|
|
12445
|
+
**\u2705 How to Get the Fixes:**
|
|
12446
|
+
|
|
12447
|
+
To retrieve the available fixes, use one of these approaches:
|
|
12448
|
+
|
|
12449
|
+
1. **Start from the beginning:**
|
|
12450
|
+
\`\`\`
|
|
12451
|
+
offset: 0
|
|
12452
|
+
\`\`\`
|
|
12453
|
+
|
|
12454
|
+
2. **Go to the first page:**
|
|
12455
|
+
\`\`\`
|
|
12456
|
+
offset: 0
|
|
12457
|
+
limit: ${limit}
|
|
12458
|
+
\`\`\`
|
|
12459
|
+
|
|
12460
|
+
3. **Get all fixes at once:**
|
|
12461
|
+
\`\`\`
|
|
12462
|
+
offset: 0
|
|
12463
|
+
limit: ${totalCount}
|
|
12464
|
+
\`\`\`
|
|
12465
|
+
|
|
12466
|
+
**\u{1F4CB} Valid offset range:** 0 to ${Math.max(0, totalCount - 1)}
|
|
12467
|
+
|
|
12468
|
+
To fetch the fixes, run the \`${currentTool}\` tool again with the corrected parameters.
|
|
12469
|
+
`;
|
|
12380
12470
|
var applyFixesPrompt = ({
|
|
12381
12471
|
fixes,
|
|
12382
12472
|
hasMore,
|
|
@@ -12384,11 +12474,22 @@ var applyFixesPrompt = ({
|
|
|
12384
12474
|
nextOffset,
|
|
12385
12475
|
shownCount,
|
|
12386
12476
|
currentTool,
|
|
12387
|
-
offset
|
|
12477
|
+
offset,
|
|
12478
|
+
limit
|
|
12388
12479
|
}) => {
|
|
12389
12480
|
if (fixes.length === 0) {
|
|
12481
|
+
if (totalCount > 0) {
|
|
12482
|
+
return noFixesReturnedForParametersWithGuidance({
|
|
12483
|
+
offset,
|
|
12484
|
+
limit,
|
|
12485
|
+
totalCount,
|
|
12486
|
+
currentTool
|
|
12487
|
+
});
|
|
12488
|
+
}
|
|
12390
12489
|
return noFixesReturnedForParameters;
|
|
12391
12490
|
}
|
|
12491
|
+
const currentPage = Math.floor(offset / limit) + 1;
|
|
12492
|
+
const totalPages = Math.ceil(totalCount / limit);
|
|
12392
12493
|
const fixList = fixes.map((fix) => {
|
|
12393
12494
|
const vulnerabilityType = friendlyType(fix.safeIssueType);
|
|
12394
12495
|
const vulnerabilityDescription = fix.patchAndQuestions?.__typename === "FixData" ? fix.patchAndQuestions.extraContext?.fixDescription : void 0;
|
|
@@ -12442,6 +12543,12 @@ If you cannot apply a patch:
|
|
|
12442
12543
|
|
|
12443
12544
|
# SECURITY FIXES TO APPLY
|
|
12444
12545
|
|
|
12546
|
+
## \u{1F4C4} Pagination Info
|
|
12547
|
+
- **Page:** ${currentPage} of ${totalPages}
|
|
12548
|
+
- **Offset:** ${offset}
|
|
12549
|
+
- **Limit:** ${limit}
|
|
12550
|
+
- **Showing:** ${shownCount} of ${totalCount} total fixes
|
|
12551
|
+
|
|
12445
12552
|
${fixList.map(
|
|
12446
12553
|
(fix, index) => `
|
|
12447
12554
|
## Fix ${offset + index + 1}: ${fix.vulnerabilityType}
|
|
@@ -12479,9 +12586,9 @@ You have viewed ${shownCount} out of ${totalCount} available fixes.
|
|
|
12479
12586
|
To fetch additional fixes, run the \`${currentTool}\` tool again with the following parameters:
|
|
12480
12587
|
|
|
12481
12588
|
- **offset**: ${nextOffset} _(start index for the next batch)_
|
|
12482
|
-
- **limit**: <number_of_fixes_to_return> _(optional \u2013 default is
|
|
12589
|
+
- **limit**: <number_of_fixes_to_return> _(optional \u2013 default is ${MCP_DEFAULT_LIMIT})_
|
|
12483
12590
|
|
|
12484
|
-
If you omit both **offset** and **limit**, the command will automatically return the next
|
|
12591
|
+
If you omit both **offset** and **limit**, the command will automatically return the next ${MCP_DEFAULT_LIMIT} fixes.
|
|
12485
12592
|
` : ""}
|
|
12486
12593
|
`;
|
|
12487
12594
|
};
|
|
@@ -12538,7 +12645,8 @@ var noFixesAvailablePrompt = `There are no fixes available for this repository a
|
|
|
12538
12645
|
`;
|
|
12539
12646
|
var fixesFoundPrompt = ({
|
|
12540
12647
|
fixReport,
|
|
12541
|
-
offset
|
|
12648
|
+
offset,
|
|
12649
|
+
limit
|
|
12542
12650
|
}) => {
|
|
12543
12651
|
const totalFixes = fixReport.filteredFixesCount.aggregate?.count || 0;
|
|
12544
12652
|
if (totalFixes === 0) {
|
|
@@ -12579,10 +12687,11 @@ ${applyFixesPrompt({
|
|
|
12579
12687
|
fixes: fixReport.fixes,
|
|
12580
12688
|
totalCount: totalFixes,
|
|
12581
12689
|
hasMore,
|
|
12582
|
-
nextOffset
|
|
12690
|
+
nextOffset,
|
|
12583
12691
|
shownCount: fixReport.fixes.length,
|
|
12584
12692
|
currentTool: MCP_TOOL_FETCH_AVAILABLE_FIXES,
|
|
12585
|
-
offset
|
|
12693
|
+
offset,
|
|
12694
|
+
limit
|
|
12586
12695
|
})}`;
|
|
12587
12696
|
};
|
|
12588
12697
|
var nextStepsPrompt = ({ scannedFiles }) => `
|
|
@@ -12619,7 +12728,8 @@ var fixesPrompt = ({
|
|
|
12619
12728
|
fixes,
|
|
12620
12729
|
totalCount,
|
|
12621
12730
|
offset,
|
|
12622
|
-
scannedFiles
|
|
12731
|
+
scannedFiles,
|
|
12732
|
+
limit
|
|
12623
12733
|
}) => {
|
|
12624
12734
|
if (totalCount === 0) {
|
|
12625
12735
|
return noFixesFoundPrompt({ scannedFiles });
|
|
@@ -12636,7 +12746,8 @@ ${applyFixesPrompt({
|
|
|
12636
12746
|
nextOffset,
|
|
12637
12747
|
shownCount,
|
|
12638
12748
|
currentTool: MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES,
|
|
12639
|
-
offset
|
|
12749
|
+
offset,
|
|
12750
|
+
limit
|
|
12640
12751
|
})}
|
|
12641
12752
|
|
|
12642
12753
|
${nextStepsPrompt({ scannedFiles })}
|
|
@@ -12644,7 +12755,10 @@ ${nextStepsPrompt({ scannedFiles })}
|
|
|
12644
12755
|
};
|
|
12645
12756
|
var noFreshFixesPrompt = `No fresh fixes available for this repository at this time. No user message needed. Do not show any comments to the user.`;
|
|
12646
12757
|
var initialScanInProgressPrompt = `Initial scan is still in progress. No user message needed. Do not show any comments to the user.`;
|
|
12647
|
-
var freshFixesPrompt = ({
|
|
12758
|
+
var freshFixesPrompt = ({
|
|
12759
|
+
fixes,
|
|
12760
|
+
limit
|
|
12761
|
+
}) => {
|
|
12648
12762
|
return `Here are the fresh fixes to the vulnerabilities discovered by Mobb MCP
|
|
12649
12763
|
|
|
12650
12764
|
${applyFixesPrompt({
|
|
@@ -12654,7 +12768,8 @@ ${applyFixesPrompt({
|
|
|
12654
12768
|
nextOffset: 0,
|
|
12655
12769
|
shownCount: fixes.length,
|
|
12656
12770
|
currentTool: MCP_TOOL_FETCH_AVAILABLE_FIXES,
|
|
12657
|
-
offset: 0
|
|
12771
|
+
offset: 0,
|
|
12772
|
+
limit
|
|
12658
12773
|
})}
|
|
12659
12774
|
`;
|
|
12660
12775
|
};
|
|
@@ -12853,7 +12968,11 @@ var FileOperations = class {
|
|
|
12853
12968
|
};
|
|
12854
12969
|
|
|
12855
12970
|
// src/mcp/services/ScanFiles.ts
|
|
12856
|
-
var scanFiles = async (
|
|
12971
|
+
var scanFiles = async ({
|
|
12972
|
+
fileList,
|
|
12973
|
+
repositoryPath,
|
|
12974
|
+
gqlClient
|
|
12975
|
+
}) => {
|
|
12857
12976
|
const repoUploadInfo = await initializeSecurityReport(gqlClient);
|
|
12858
12977
|
const fixReportId = repoUploadInfo.fixReportId;
|
|
12859
12978
|
const fileOperations = new FileOperations();
|
|
@@ -12864,7 +12983,17 @@ var scanFiles = async (fileList, repositoryPath, gqlClient) => {
|
|
|
12864
12983
|
);
|
|
12865
12984
|
await uploadSourceCodeArchive(packingResult.archive, repoUploadInfo);
|
|
12866
12985
|
const projectId = await getProjectId(gqlClient);
|
|
12867
|
-
|
|
12986
|
+
const gitService = new GitService(repositoryPath);
|
|
12987
|
+
const { branch } = await gitService.getCurrentCommitAndBranch();
|
|
12988
|
+
const repoUrl = await gitService.getRemoteUrl();
|
|
12989
|
+
await executeSecurityScan({
|
|
12990
|
+
fixReportId,
|
|
12991
|
+
projectId,
|
|
12992
|
+
gqlClient,
|
|
12993
|
+
repoUrl: repoUrl || "",
|
|
12994
|
+
branchName: branch || "no-branch",
|
|
12995
|
+
sha: "0123456789abcdef"
|
|
12996
|
+
});
|
|
12868
12997
|
return {
|
|
12869
12998
|
fixReportId,
|
|
12870
12999
|
projectId
|
|
@@ -12919,7 +13048,10 @@ var getProjectId = async (gqlClient) => {
|
|
|
12919
13048
|
var executeSecurityScan = async ({
|
|
12920
13049
|
fixReportId,
|
|
12921
13050
|
projectId,
|
|
12922
|
-
gqlClient
|
|
13051
|
+
gqlClient,
|
|
13052
|
+
repoUrl,
|
|
13053
|
+
branchName,
|
|
13054
|
+
sha
|
|
12923
13055
|
}) => {
|
|
12924
13056
|
if (!gqlClient) {
|
|
12925
13057
|
throw new GqlClientError();
|
|
@@ -12928,11 +13060,15 @@ var executeSecurityScan = async ({
|
|
|
12928
13060
|
const submitVulnerabilityReportVariables = {
|
|
12929
13061
|
fixReportId,
|
|
12930
13062
|
projectId,
|
|
12931
|
-
repoUrl
|
|
12932
|
-
reference:
|
|
12933
|
-
scanSource: "MCP" /* Mcp
|
|
13063
|
+
repoUrl,
|
|
13064
|
+
reference: branchName,
|
|
13065
|
+
scanSource: "MCP" /* Mcp */,
|
|
13066
|
+
sha
|
|
12934
13067
|
};
|
|
12935
13068
|
logInfo("Submitting vulnerability report");
|
|
13069
|
+
logDebug("Submit vulnerability report variables", {
|
|
13070
|
+
submitVulnerabilityReportVariables
|
|
13071
|
+
});
|
|
12936
13072
|
const submitRes = await gqlClient.submitVulnerabilityReport(
|
|
12937
13073
|
submitVulnerabilityReportVariables
|
|
12938
13074
|
);
|
|
@@ -13035,11 +13171,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
13035
13171
|
return;
|
|
13036
13172
|
}
|
|
13037
13173
|
logDebug("Files requiring security scan", { filesToScan });
|
|
13038
|
-
const { fixReportId, projectId } = await scanFiles(
|
|
13039
|
-
filesToScan.map((file) => file.relativePath),
|
|
13040
|
-
path13,
|
|
13041
|
-
this.gqlClient
|
|
13042
|
-
);
|
|
13174
|
+
const { fixReportId, projectId } = await scanFiles({
|
|
13175
|
+
fileList: filesToScan.map((file) => file.relativePath),
|
|
13176
|
+
repositoryPath: path13,
|
|
13177
|
+
gqlClient: this.gqlClient
|
|
13178
|
+
});
|
|
13043
13179
|
logInfo(
|
|
13044
13180
|
`Security scan completed for ${path13} reportId: ${fixReportId} projectId: ${projectId}`
|
|
13045
13181
|
);
|
|
@@ -13130,10 +13266,10 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
13130
13266
|
});
|
|
13131
13267
|
}
|
|
13132
13268
|
generateFreshFixesResponse() {
|
|
13133
|
-
const freshFixes = this.freshFixes.splice(0,
|
|
13269
|
+
const freshFixes = this.freshFixes.splice(0, MCP_DEFAULT_LIMIT);
|
|
13134
13270
|
if (freshFixes.length > 0) {
|
|
13135
13271
|
this.reportedFixes.push(...freshFixes);
|
|
13136
|
-
return freshFixesPrompt({ fixes: freshFixes });
|
|
13272
|
+
return freshFixesPrompt({ fixes: freshFixes, limit: MCP_DEFAULT_LIMIT });
|
|
13137
13273
|
}
|
|
13138
13274
|
return noFreshFixesPrompt;
|
|
13139
13275
|
}
|
|
@@ -13232,7 +13368,7 @@ var _FetchAvailableFixesService = class _FetchAvailableFixesService {
|
|
|
13232
13368
|
}
|
|
13233
13369
|
async checkForAvailableFixes({
|
|
13234
13370
|
repoUrl,
|
|
13235
|
-
limit =
|
|
13371
|
+
limit = MCP_DEFAULT_LIMIT,
|
|
13236
13372
|
offset
|
|
13237
13373
|
}) {
|
|
13238
13374
|
try {
|
|
@@ -13264,7 +13400,8 @@ var _FetchAvailableFixesService = class _FetchAvailableFixesService {
|
|
|
13264
13400
|
logInfo(`Successfully retrieved available fixes for ${repoUrl}`);
|
|
13265
13401
|
const prompt = fixesFoundPrompt({
|
|
13266
13402
|
fixReport,
|
|
13267
|
-
offset: effectiveOffset
|
|
13403
|
+
offset: effectiveOffset,
|
|
13404
|
+
limit
|
|
13268
13405
|
});
|
|
13269
13406
|
this.currentOffset = effectiveOffset + (fixReport.fixes?.length || 0);
|
|
13270
13407
|
return prompt;
|
|
@@ -13429,21 +13566,22 @@ var _ScanAndFixVulnerabilitiesService = class _ScanAndFixVulnerabilitiesService
|
|
|
13429
13566
|
logInfo("Scanning files");
|
|
13430
13567
|
this.reset();
|
|
13431
13568
|
this.validateFiles(fileList);
|
|
13432
|
-
const scanResult = await scanFiles(
|
|
13569
|
+
const scanResult = await scanFiles({
|
|
13433
13570
|
fileList,
|
|
13434
13571
|
repositoryPath,
|
|
13435
|
-
this.gqlClient
|
|
13436
|
-
);
|
|
13572
|
+
gqlClient: this.gqlClient
|
|
13573
|
+
});
|
|
13437
13574
|
fixReportId = scanResult.fixReportId;
|
|
13438
13575
|
} else {
|
|
13439
13576
|
logInfo("Using stored fixReportId");
|
|
13440
13577
|
}
|
|
13441
13578
|
const effectiveOffset = offset ?? (this.currentOffset || 0);
|
|
13579
|
+
const effectiveLimit = limit ?? MCP_DEFAULT_LIMIT;
|
|
13442
13580
|
logDebug("effectiveOffset", { effectiveOffset });
|
|
13443
13581
|
const fixes = await this.getReportFixes(
|
|
13444
13582
|
fixReportId,
|
|
13445
13583
|
effectiveOffset,
|
|
13446
|
-
|
|
13584
|
+
effectiveLimit
|
|
13447
13585
|
);
|
|
13448
13586
|
logInfo(`Found ${fixes.totalCount} fixes`);
|
|
13449
13587
|
if (fixes.totalCount > 0) {
|
|
@@ -13456,7 +13594,8 @@ var _ScanAndFixVulnerabilitiesService = class _ScanAndFixVulnerabilitiesService
|
|
|
13456
13594
|
fixes: fixes.fixes,
|
|
13457
13595
|
totalCount: fixes.totalCount,
|
|
13458
13596
|
offset: effectiveOffset,
|
|
13459
|
-
scannedFiles: [...fileList]
|
|
13597
|
+
scannedFiles: [...fileList],
|
|
13598
|
+
limit: effectiveLimit
|
|
13460
13599
|
});
|
|
13461
13600
|
this.currentOffset = effectiveOffset + (fixes.fixes?.length || 0);
|
|
13462
13601
|
return prompt;
|
|
@@ -13619,7 +13758,7 @@ Example payload:
|
|
|
13619
13758
|
try {
|
|
13620
13759
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
13621
13760
|
fileList: files.map((file) => file.relativePath),
|
|
13622
|
-
repositoryPath:
|
|
13761
|
+
repositoryPath: path13,
|
|
13623
13762
|
offset: args.offset,
|
|
13624
13763
|
limit: args.limit,
|
|
13625
13764
|
isRescan: args.rescan || !!args.maxFiles
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobbdev",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.117",
|
|
4
4
|
"description": "Automated secure code remediation tool",
|
|
5
5
|
"repository": "git+https://github.com/mobb-dev/bugsy.git",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@gitbeaker/requester-utils": "42.5.0",
|
|
48
48
|
"@gitbeaker/rest": "42.5.0",
|
|
49
|
-
"@modelcontextprotocol/sdk": "1.
|
|
49
|
+
"@modelcontextprotocol/sdk": "1.15.1",
|
|
50
50
|
"@octokit/core": "5.2.0",
|
|
51
51
|
"@octokit/request-error": "5.1.1",
|
|
52
52
|
"adm-zip": "0.5.16",
|
|
53
|
-
"axios": "1.
|
|
54
|
-
"azure-devops-node-api": "
|
|
53
|
+
"axios": "1.10.0",
|
|
54
|
+
"azure-devops-node-api": "15.1.0",
|
|
55
55
|
"bitbucket": "2.11.0",
|
|
56
56
|
"chalk": "5.4.1",
|
|
57
57
|
"chalk-animation": "2.0.3",
|
|
58
58
|
"configstore": "6.0.0",
|
|
59
59
|
"cross-fetch": "4.1.0",
|
|
60
60
|
"debug": "4.4.1",
|
|
61
|
-
"dotenv": "16.
|
|
61
|
+
"dotenv": "16.6.1",
|
|
62
62
|
"extract-zip": "2.0.1",
|
|
63
63
|
"globby": "14.1.0",
|
|
64
64
|
"graphql": "16.11.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"graphql-ws": "5.16.2",
|
|
67
67
|
"http-proxy-agent": "7.0.2",
|
|
68
68
|
"https-proxy-agent": "7.0.6",
|
|
69
|
-
"inquirer": "9.
|
|
69
|
+
"inquirer": "9.3.7",
|
|
70
70
|
"isomorphic-ws": "5.0.0",
|
|
71
71
|
"istextorbinary": "6.0.0",
|
|
72
72
|
"libsodium-wrappers": "0.7.15",
|
|
@@ -80,15 +80,15 @@
|
|
|
80
80
|
"sax": "1.4.1",
|
|
81
81
|
"semver": "7.7.2",
|
|
82
82
|
"simple-git": "3.28.0",
|
|
83
|
-
"snyk": "1.1297.
|
|
83
|
+
"snyk": "1.1297.3",
|
|
84
84
|
"tar": "6.2.1",
|
|
85
85
|
"tmp": "0.2.3",
|
|
86
86
|
"undici": "6.21.3",
|
|
87
87
|
"uuid": "11.1.0",
|
|
88
|
-
"ws": "8.18.
|
|
88
|
+
"ws": "8.18.3",
|
|
89
89
|
"xml2js": "0.6.2",
|
|
90
90
|
"yargs": "17.7.2",
|
|
91
|
-
"zod": "3.25.
|
|
91
|
+
"zod": "3.25.76"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@graphql-codegen/cli": "5.0.7",
|
|
@@ -113,19 +113,19 @@
|
|
|
113
113
|
"@types/yargs": "17.0.33",
|
|
114
114
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
|
115
115
|
"@typescript-eslint/parser": "7.17.0",
|
|
116
|
-
"@vitest/coverage-istanbul": "3.2.
|
|
117
|
-
"@vitest/ui": "3.2.
|
|
116
|
+
"@vitest/coverage-istanbul": "3.2.4",
|
|
117
|
+
"@vitest/ui": "3.2.4",
|
|
118
118
|
"eslint": "8.57.0",
|
|
119
119
|
"eslint-plugin-graphql": "4.0.0",
|
|
120
|
-
"eslint-plugin-import": "2.
|
|
121
|
-
"eslint-plugin-prettier": "5.
|
|
122
|
-
"eslint-plugin-simple-import-sort": "
|
|
123
|
-
"msw": "2.
|
|
120
|
+
"eslint-plugin-import": "2.32.0",
|
|
121
|
+
"eslint-plugin-prettier": "5.5.1",
|
|
122
|
+
"eslint-plugin-simple-import-sort": "12.1.1",
|
|
123
|
+
"msw": "2.10.4",
|
|
124
124
|
"nock": "14.0.5",
|
|
125
|
-
"prettier": "3.
|
|
125
|
+
"prettier": "3.6.2",
|
|
126
126
|
"tsup": "8.5.0",
|
|
127
127
|
"typescript": "4.9.5",
|
|
128
|
-
"vitest": "3.2.
|
|
128
|
+
"vitest": "3.2.4"
|
|
129
129
|
},
|
|
130
130
|
"engines": {
|
|
131
131
|
"node": ">=18.20.0"
|